Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on May 14, 2024. It is now read-only.

Homework Week3 #40

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Homework week3
- https://neveenatik.github.io/JavaScript3/Week3

> Please help us improve and share your feedback! If you find better tutorials
or links, please share them by [opening a pull request](https://github.com/HackYourFuture/JavaScript3/pulls).

Expand Down
3 changes: 3 additions & 0 deletions Week3/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Homework week3
- https://neveenatik.github.io/JavaScript3/Week3

# Reading material for the third lecture:

```
Expand Down
165 changes: 165 additions & 0 deletions Week3/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
'use strict';

{

let mainUrl = `https://api.github.com/`;
let user = `HackYourFuture`;
let userUrl = `${mainUrl}users/${user}`;
let repositoryUrl = `${userUrl}/repos?per_page=100`;
const root = document.getElementById('root');
const headerWrapper = createAndAppend('div', root, { class: 'header-wrapper', role: 'navigation' });
const header = createAndAppend('h2', headerWrapper, { html: `Repositories `, id: 'repositories' });
const inputRepository = createAndAppend('input', header, { type: 'text', id: 'input-user', value: `${user}`, role: 'enter new username' });
const inputButton = createAndAppend('button', header, { type: 'submit', html: 'Edit GitHub name and click', for: 'input-user' });
const headerImg = createAndAppend('img', header, { class: 'header-img', src: 'assets/doubleblink.webp', alt: 'blinking octodex' });
inputButton.addEventListener('click', () => {
user = inputRepository.value;
headerImg.classList.remove('onclick-image');
//triggering reflow calculating style
void headerImg.offsetWidth;
headerImg.classList.add('onclick-image')
repositoryUrl = `${mainUrl}users/${user}/repos?per_page=100`;
removeChildElements('wrapper');
main();
});
const wrapper = createAndAppend('div', root, { id: 'wrapper' });

async function main() {
try {
let fetchRepositories = await fetchJSON(repositoryUrl);
let renderedRepositoriesList = createRepositoryList(fetchRepositories);
let chooseAndFetch = await fetchJSON(`${mainUrl}repos/${user}/${renderedRepositoriesList}`);
let renderRepositories = renderRepositoryInfo(chooseAndFetch);
let contributionData = await fetchJSON(renderRepositories['contributors_url']);
renderContributionsInfo(contributionData);
}
catch (error) {
createAndAppend('div', wrapper, { html: error.message, class: 'alert-error', role: 'alert' });
}
}

function fetchJSON(url) {
return new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';
xhr.onload = () => xhr.status < 400 ? resolve(xhr.response) : reject(new Error(`Network error: ${xhr.status} - ${xhr.statusText}`));
xhr.onerror = () => reject(new Error('Network request failed'));
xhr.send();
});
}

function createRepositoryList(response) {
const dropList = createAndAppend('select', wrapper, { id: 'repository-list' });
Object.values(response).forEach(repo => {
createAndAppend('option', dropList, { html: repo.name, });
});
const selected = document.getElementById('repository-list');
createAndAppend('div', wrapper, { id: 'container' });
selected.addEventListener('change', async () => {
try {
removeChildElements('container');
let chooseAndFetch = await fetchJSON(`${mainUrl}repos/${user}/${selected.value}`);
let renderRepositories = renderRepositoryInfo(chooseAndFetch);
let contributionData = await fetchJSON(renderRepositories['contributors_url']);
renderContributionsInfo(contributionData);
}
catch (error) {
removeChildElements('container');
createAndAppend('div', wrapper, { html: `Error in rendering repositories on change ${error.message}`, class: 'alert-error', role: 'alert' });
}
});
return selected.value;
}

function renderRepositoryInfo(repoData) {
try {
const container = document.getElementById('container');
const section = createAndAppend('section', container, { class: 'repository-info' });
createAndAppend('div', section, { id: 'repository' });
renderTable(section,
{
repository: repoData['name'],
description: repoData['description'],
forks: repoData['forks'],
'last update': ((repoData['updated_at']).substring(0, 10) + ' at ' + (repoData['updated_at']).substring(11, 19)),
},
repoData['html_url'],
);
} catch {
createAndAppend('div', wrapper, { html: `Error in rendering repository information ${error.message}`, class: 'alert-error', role: 'alert' });
}
return repoData;
}

function renderContributionsInfo(contData) {
try {
const container = document.getElementById('container');
const section = createAndAppend('section', container, { class: 'contributions-info' });
createAndAppend('h3', section, { html: 'Contributions' });
contData.forEach(cont => {
const contributorContainer = createAndAppend('div', section, { class: 'contributor', id: cont['login'] });
createAndAppend('img', contributorContainer, { src: cont['avatar_url'], class: 'avatar-img', alt: 'user avatar', for: cont['login'] });
const linkUser = createAndAppend('a', contributorContainer, { href: cont['html_url'], target: '_blank', html: cont['login'], class: 'name', for: cont['login'] });
createAndAppend('p', contributorContainer, { html: cont['contributions'], class: 'contributions', for: cont['login'] });
linkUser.addEventListener('click', () => {
user = linkUser.innerText;
inputRepository.value = user;
repositoryUrl = `${mainUrl}users/${user}/repos?per_page=100`;
removeChildElements('wrapper');
main();
});
});
} catch {
createAndAppend('div', wrapper, { html: `Error in rendering contributions information ${error.message}`, class: 'alert-error', role: 'alert' });
}
}

function createAndAppend(name, parent, options = {}) {
const element = document.createElement(name);
parent.appendChild(element);
Object.keys(options).forEach((key) => {
const value = options[key];
if (key === 'html') {
element.innerHTML = value;
} else {
element.setAttribute(key, value);
}
});
return element;
}

function removeChildElements(elementId) {
const garbage = document.getElementById(elementId);
while (garbage.hasChildNodes()) {
garbage.removeChild(garbage.firstChild);
}
}

function renderTable(parent, values = {}, href) {
let table = createAndAppend('table', parent, { class: 'table' });
Object.keys(values).forEach((key) => {
if (key === 'repository') {
let secondCell = renderRowAndCell(key);
secondCell.innerText = '';
createAndAppend('a', secondCell, { html: values[key], href: href, target: '_blank' });
} else if (key === 'avatar') {
let firstCell = renderRowAndCell(key);
createAndAppend('img', firstCell, { src: href });
} else {
renderRowAndCell(key);
}
});

function renderRowAndCell(cellKey) {
let newRow = table.insertRow();
let firstCell = newRow.insertCell(0);
firstCell.innerText = cellKey + ': ';
let secondCell = newRow.insertCell(1);
secondCell.innerText = values[cellKey];
return secondCell;
}
}

window.onload = main();
}
Binary file added Week3/assets/doubleblink.webp
Binary file not shown.
Binary file added Week3/assets/github.ico
Binary file not shown.
Binary file added Week3/assets/hyf-github-error.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Week3/assets/hyf-github.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Week3/assets/hyf.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions Week3/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>GitHub API</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="style.css" />
<link rel="shortcut icon" type="image/x-icon" href="assets/github.ico" />
</head>
<body>
<div id="root"></div>
<script src="app.js"></script>
</body>
</html>
159 changes: 159 additions & 0 deletions Week3/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@

* {
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.header-wrapper {
color: white;
background-color: #0d0d85;
padding: 2rem;
-moz-box-shadow: 0 8px 6px -6px #bab9b9;
-webkit-box-shadow: 0 8px 6px -6px #bab9b9;
box-shadow: 0 8px 6px -6px #bab9b9;
position: fixed;
top: -1rem;
width: 100vw;
z-index: 1;
}

select {
margin-left: 1rem;
border-radius: 0.5rem;
position: fixed;
top: 7.5rem;
left: 1rem;
z-index: 1;
}

#input-user {
color: white;
background-color: #0d0d85;
border: none;
font-size: 1.5rem;
font-weight: bold;
}

button {
margin-top: 0.75rem;
display: block;
}

.header-img {
position: fixed;
top : 2rem;
right: 1rem;
box-shadow: none;
}

@keyframes bounce {
0%, 20%, 50%, 80%, 100% {transform: translateY(0);}
40% {transform: translateY(-30px);}
60% {transform: translateY(-20px);}
}


.onclick-image {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-name: bounce;
animation-name: bounce;
box-shadow: none;
position: fixed;
top: 2rem;
right: 1rem;
}

section {
-moz-box-shadow: inset 0 0 10px #bab9b9;
-webkit-box-shadow: inset 0 0 10px #bab9b9;
box-shadow: inset 0 0 10px #bab9b9;
margin: 1rem;
padding: 1rem;
border-radius: 10px;
position: relative;
top: 10rem;
}

h3 {
color: gray;
padding: 1rem;
}

a {
text-decoration: none;
font-weight: bold;
}

td {
vertical-align: text-top;
}

td:nth-child(1) {
font-weight: bold;
padding: 1rem;
}

.contributor {
padding: 1rem;
border-bottom: 1px solid #d3d3d3;
}

img {
width: 3.5rem;
margin: 0 0.5rem;
max-height: 3.5rem;
-moz-box-shadow: 0px 2px 1px #ccc;
-webkit-box-shadow: 0px 2px 1px #ccc;
box-shadow: 0px 2px 1px #ccc;
border-radius: 10px;
}

.contributions {
margin-top: 1.75rem;
float: right;
text-align: center;
min-width: 2.5rem;
background-color: gray;
color: white;
border-radius: 5px;
}

.name {
position: relative;
top: -1rem;
font-weight: bold;
}

.alert-error {
color: red;
background-color: rgb(248, 212, 212);
margin: 1rem 0.25rem;
padding: 0.5rem;
text-align: left;
border-radius: 0.5rem;
clear: both;
position: relative;
top: 10rem;
}

@media (min-width:768px) {
.header-wrapper {
top: 0;
}

section {
width: calc(50% - 4rem);
float: left;
}

select {
margin-left: 1rem;
border-radius: 0.5rem;
position: fixed;
top: 2.75rem;
left: 60%;
z-index: 1;
}
}