Skip to content

Instantly share code, notes, and snippets.

@fxg42
Created July 17, 2019 15:39
Show Gist options
  • Save fxg42/3f167a8f6ff78ef3baf4058044dc3775 to your computer and use it in GitHub Desktop.
Save fxg42/3f167a8f6ff78ef3baf4058044dc3775 to your computer and use it in GitHub Desktop.
INF5190 - Exemple d'une application MVC
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)
<!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