API workshop
API
What is an API?
Application
Programming
Interface
![](https://s3.amazonaws.com/media-p.slid.es/uploads/693073/images/5503219/ezgif.com-gif-maker.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/693073/images/5503240/ezgif.com-video-to-gif.gif)
Kitchen
You
News API
const app = new App();
app.start();
main.js
class App {
constructor() {
this.controller = new AppController();
this.view = new AppView();
}
start() {
document.querySelector('.sources')
.addEventListener('click',
e => this.controller.getNews(e, data => this.view.drawNews(data))
);
this.controller.getSources(data => this.view.drawSources(data));
}
}
App.js
class AppController extends NewsAPILoader {
getSources(callback) {
super.getResp({
endpoint: 'sources'
}, callback);
}
getNews(e, callback) {
if (e.target.classList.contains('source__item')) {
super.getResp({
endpoint: 'everything',
options: { sources: sourceId }
}, callback);
}
}
}
AppController.js
class NewsAPILoader {
constructor(baseLink, settings) {
this.baseLink = 'https://newsapi.org/v2/',
this.settings = {
apiKey: '67c1acd35f714c8da11288faf6e12bcf'
}
}
_makeUrl(options, endpoint){
const urlOptions = { ...this.settings, ...options };
let url = `${this.baseLink}${endpoint}?`;
for (let i in urlOptions) url += `${i}=${urlOptions[i]}&`;
return url.slice(0, -1);
}
getResp({ endpoint, options = {} }, callback) {
fetch(this._makeUrl(options, endpoint))
.then(res => res.json())
.then(data => callback(data))
.catch(err => console.error(err));
}
}
NewsAPILoader.js
class AppView {
constructor() {
this.news = new News();
this.sources = new Sources();
}
drawNews(data) {
this.news.draw(data.articles);
}
drawSources(data) {
this.sources.draw(data.sources);
}
}
AppView.js
class Sources {
draw(data) {
const fragment = document.createDocumentFragment();
const sourceItemTemp = document.querySelector('#sourceItemTemp');
for (let i = 0; i < data.length; i++) {
const item = data[i];
const sourceClone = sourceItemTemp.content.cloneNode(true);
const sourceButton = sourceClone.querySelector('.source__item');
sourceButton.textContent = item.name;
sourceButton.setAttribute('data-source-id', item.id);
fragment.appendChild(sourceClone);
}
document.querySelector('.sources').appendChild(fragment);
}
}
Sources.js
class News {
draw(data) {
let newsCount = (data.length >= 10) ? 10 : data.length;
const fragment = document.createDocumentFragment();
const newsItemTemp = document.querySelector('#newsItemTemp');
for (let i = 0; i < newsCount; i++) {
const item = data[i];
const newsClone = newsItemTemp.content.cloneNode(true);
newsClone.querySelector('.news__meta-photo')
.style
.backgroundImage = `url(${item.urlToImage || 'img/news_placeholder.jpg'})`;
newsClone.querySelector('.news__meta-author')
.textContent = item.author || item.source.name;
newsClone.querySelector('.news__meta-date')
.textContent = item.publishedAt.slice(0, 10).split('-').reverse().join('-');
newsClone.querySelector('.news__description-title')
.textContent = item.title;
newsClone.querySelector('.news__description-source')
.textContent = item.source.name;
newsClone.querySelector('.news__description-content')
.textContent = item.description;
newsClone.querySelector('.news__read-more a')
.setAttribute('href', item.url);
fragment.appendChild(newsClone);
}
document.querySelector('.news').innerHTML = '';
document.querySelector('.news').appendChild(fragment);
}
}
News.js
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>PewNews</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<header>
<h1>PewNews</h1>
</header>
<main>
<div class="sources"></div>
<div class="news"></div>
</main>
<footer>
<p class="copyright">Copyright <a href="https://newsapi.org">NewsAPI</a></p>
</footer>
<template id="sourceItemTemp">
<button class="source__item"></button>
</template>
<template id="newsItemTemp">
<section class="news__item">
<div class="news__meta">
<div class="news__meta-photo"></div>
<ul class="news__meta-details">
<li class="news__meta-author"></li>
<li class="news__meta-date"></li>
</ul>
</div>
<article class="news__description">
<h2 class="news__description-title"></h2>
<h3 class="news__description-source"></h3>
<p class="news__description-content"></p>
<p class="news__read-more">
<a href="#">Read More</a>
</p>
</article>
</section>
</template>
<script src="js/NewsAPILoader.js"></script>
<script src="js/AppController.js"></script>
<script src="js/News.js"></script>
<script src="js/Sources.js"></script>
<script src="js/AppView.js"></script>
<script src="js/App.js"></script>
<script src="js/main.js"></script>
</body>
</html>
index.html
Task
- 1,5 hour
- App must work!
- One button and only you decide what it should do
- Purely client side
- No frameworks!
- At least minimal styling
- Separate files
- Create build in the end (gh-pages)
- ES5 or ES6+
- Functions or Classes
- XMLHttpRequest or fetch or async
- Template or createElement()
Should
Decide
- Разбейтесь на группы по 4 человека
- Будет круто, если вы найдете кого-то из своей менторской группы
- Определитесь с задачами каждого участника группы (верстка, запрос, вывод и тд...)
- Создайте репозиторий на GitHub
- Добавьте в него контрибьютеров
- Склоньте его себе локально
- Работайте!!!
- В конце представьте свой проект (5 минут)
- Обоснуйте выбор тех или иных методов (why fetch, why Classes)
So...
master
Request Branch
FE Branch
Output Branch
Branches
GH-PAGES
- Create branch 'gh-pages' from master
- Go to environment tab
- Here is your builds
- First one is what you need
![](https://s3.amazonaws.com/media-p.slid.es/uploads/693073/images/5503581/Снимок_экрана_2018-11-19_в_15.47.57.png)
ColLaborators
![](https://s3.amazonaws.com/media-p.slid.es/uploads/693073/images/5503724/Снимок_экрана_2018-11-19_в_16.10.06.png)
API
By Victoria Budyonnaya
API
- 325