API workshop

API

What is an API?

Application

Programming

Interface

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. 1,5 hour
  2. App must work!
  3. One button and only  you decide what it should do
  4. Purely client side
  5. No frameworks!
  6. At least minimal styling
  7. Separate files
  8. Create build in the end (gh-pages)
  1. ES5 or ES6+
  2. Functions or Classes
  3. XMLHttpRequest or fetch or async
  4. Template or createElement()

Should

Decide

  1. Разбейтесь на группы по 4 человека
  2. Будет круто, если вы найдете кого-то из своей менторской группы
  3. Определитесь с задачами каждого участника группы (верстка, запрос, вывод и тд...)
  4. Создайте репозиторий на GitHub
  5. Добавьте в него контрибьютеров
  6. Склоньте его себе локально
  7. Работайте!!!
  8. В конце представьте свой проект (5 минут)
  9. Обоснуйте выбор тех или иных методов (why fetch, why Classes)

So...

master

Request Branch

FE Branch

Output Branch

Branches

GH-PAGES

  1. Create branch 'gh-pages' from master
  2. Go to environment tab
  3. Here is your builds
  4. First one is what you need

ColLaborators

API

By Victoria Budyonnaya