Created
July 17, 2019 15:39
-
-
Save fxg42/3f167a8f6ff78ef3baf4058044dc3775 to your computer and use it in GitHub Desktop.
INF5190 - Exemple d'une application MVC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Model { | |
constructor() { | |
this.userCollection = [ ] | |
this.selectedUser = null | |
this.listeners = { | |
'selectedUser': [ ], | |
'userCollection': [ ] | |
} | |
} | |
setSelectedUser(login) { | |
this.selectedUser = this.userCollection.filter((u) => u.login === login)[0] | |
this.notify('selectedUser') | |
} | |
addUser(user) { | |
this.userCollection.push(user) | |
this.notify('userCollection') | |
} | |
notify(eventName) { | |
this.listeners[eventName].forEach((listener) => listener(this)) | |
} | |
addChangeListener(eventName, fn) { | |
this.listeners[eventName].push(fn) | |
} | |
} | |
const model = new Model() | |
const renderUserItemView = (user) => | |
`<div class='media'> | |
<div class='media-left'> | |
<a href='#' class='user-link' data-login='${user.login}'> | |
<img src='${user.avatar_url}' style='width:64px;' class='img-circle'> | |
</a> | |
</div> | |
<div class='media-body'> | |
<h4 class='media-heading'>${user.login}</h4> | |
<p>${user.bio || user.name || user.company || user.location || user.created_at}</p> | |
</div> | |
</div>` | |
const renderUserCollectionView = (model) => { | |
document.getElementById('user-collection').innerHTML = `<div>${model.userCollection.map(renderUserItemView).join('')}</div>` | |
document.querySelectorAll('.user-link').forEach((linkEl) => { | |
linkEl.addEventListener('click', (evt) => { | |
evt.preventDefault() | |
model.setSelectedUser(linkEl.getAttribute('data-login')) | |
}) | |
}) | |
} | |
const renderRepoItemView = (repo) => | |
`<h4><a href='${repo.html_url}'>${repo.name}</a> <small>${repo.description}</small></h4>` | |
const renderSelectedUserView = (model) => { | |
const user = model.selectedUser | |
document.getElementById('selected-user').innerHTML = ` | |
<h2>${user.name || user.login}</h2> | |
${ user.location ? "<p><span class='glyphicon glyphicon-map-marker'></span> "+ user.location +"</p>" : ''} | |
${ user.company ? "<p><span class='glyphicon glyphicon-briefcase'></span> "+ user.company +"</p>" : ''} | |
<p><span class='glyphicon glyphicon-time'></span> Joined on ${user.created_at.slice(0,10)}</p> | |
<h3>Repositories</h3> | |
${user.repos.map(renderRepoItemView).join('')} | |
` | |
} | |
const fetchUserRepos = async (user) => { | |
const resp = await fetch(user.repos_url) | |
const repos = await resp.json() | |
user.repos = repos | |
model.addUser(user) | |
model.setSelectedUser(user.login) | |
} | |
const fetchUser = async (username) => { | |
const resp = await fetch(`https://api.github.com/users/${username}`) | |
const user = await resp.json() | |
fetchUserRepos(user) | |
} | |
const bindForm = () => { | |
const input = document.getElementById('user-input') | |
const form = document.getElementById('user-search-form') | |
form.addEventListener('submit', (evt) => { | |
evt.preventDefault() | |
fetchUser(input.value.toLowerCase()) | |
}) | |
} | |
model.addChangeListener('userCollection', renderUserCollectionView) | |
model.addChangeListener('selectedUser', renderSelectedUserView) | |
document.addEventListener('DOMContentLoaded', bindForm) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Github</title> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css"> | |
</head> | |
<body> | |
<nav class="navbar navbar-default"> | |
<div class="container"> | |
<a class="navbar-brand" href="#">Github users</a> | |
<form class="navbar-form navbar-left" role="search" id="user-search-form"> | |
<div class="form-group"> | |
<input type="text" class="form-control" placeholder="search users e.g. fxg42" id="user-input"> | |
</div> | |
</form> | |
</div> | |
</nav> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-3" id="user-collection"> | |
</div> | |
<div class="col-md-7" id="selected-user"> | |
</div> | |
</div> | |
</div> | |
<script src="github-mvc-es2019.js"></script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment