JSFiddle - React, Tailwind, and code Playground

by knrm720

HTML

<script src="https://cdn.jsdelivr.net/kefir/3.1.0/kefir.js"></script>
<h3>GitHub repos search</h3>
<p>To see a error, dissable internet connection, or just play with it for a while and you'll <a target="_blank" href="https://developer.github.com/v3/#rate-limiting">exceed GitHub API rate limit</a>.</p>

<p>Also open up the DevTools to see that requests in which we not interested any more are being canceled.</p>

<input type="text" id="search-query" placeholder="search..." />
<div id="search-result"></div>

JavaScript

// General utility functions

// Accepts `jQuery.ajax` options.
// Returns a Propery that will contain single value or error.
// The request is send at the moment the property gets a subscriber,
// and if it loses all subscribers before the response, the request will be canceled.
function ajax(options) {
  return Kefir.stream(function(emitter) {
    var jqXHR = $.ajax(options);
    jqXHR.done(emitter.emit);
    jqXHR.fail(function(jqXHR, textStatus, errorThrown) {
      emitter.error(jqXHR.status === 0 ? 'Connection problem' : jqXHR.responseText);
    });
    return function() {
      jqXHR.abort();
    }
  }).take(1).takeErrors(1).toProperty();
}

// Returns a Property containig current input value
function inputValue(input) {
  function getValue() {
    return input.value;
  }
  return Kefir
    .fromEvents(input, 'input', getValue)
    .toProperty(getValue);
}



// Less general utility functions

function search(queryStr) {
  return ajax({
    url: 'https://api.github.com/search/repositories',
    data: {
      q: queryStr,
      sort: 'stars',
      order: 'desc'
    }
  }).map(function(data) {
    return data.items;
  });
}



// Pure render functions

function renderLoading() {
  return '<span>loading...</span>';
}

function renderError(error) {
  return '<span style="color:red">' + error + '</span>';
}

function renderResults(items) {
  // Who needs React, when we have concatination?
  return '<ul>' + items.map(function(item) {
    return '<li><a target="_blank" href="' + item.html_url + '">' + item.full_name + '</a> (' + item.stargazers_count + ')</li>';
  }).join('') + '</ul>';
}



// Main app code

var searchQuery = inputValue(document.querySelector('#search-query'));

var searchResult = searchQuery.flatMapLatest(function(queryStr) {
  return queryStr.length > 0 ? search(queryStr) : Kefir.constant([]);
});

var resultHtml = Kefir.merge([
  searchQuery.map(renderLoading),
  searchResult.map(renderResults),
 ...