JSFiddle - React, Tailwind, and code Playground

Simple iTunes search using basis.js ,,, Search by filters via server. Also example demonstrates how build your own component classes. Framework's components are not using. ,,, forked from http://jsfiddle.net/onigetoc/L9x2ydpq/

by dledle2

HTML

<script src="http://yourjavascript.com/24215954185/basisjs-1-2-5-dev.js"></script>
<script type="text/basis-template" id="toolbar">
  <div class="toolbar">
    <!--{searchField}--> <!--{countryField}--> <!--{typeField}-->
  </div>
</script>

<script type="text/basis-template" id="field-text">
  <input value="{value}" placeholder="Search..." event-keyup="updateValue" event-change="updateValue"/>
</script>

<script type="text/basis-template" id="field-select">
  <select value="{value}" event-change="updateValue"/>
</script>

<script type="text/basis-template" id="field-select-item">
  <option value="{value}">{caption}</option>
</script>
      
<script type="text/basis-template" id="entry-list">
  <div>
    <!--{toolbar}-->
    <!--{childNodesHere}-->
    <div class="entry-list__loading entry-list__loading_{childNodesState}">loading...</div>
    <div class="entry-list__empty entry-list__empty_{childNodesState} entry-list__empty_{empty}">Nothing found</div>
  </div>
</script>
      
<script type="text/basis-template" id="entry">
  <div class="entry">
    <img class="entry__image" src="{thumbnail}" height="100"/>
    <span class="entry__description">
      <span class="entry__name">{name}</span>
      <span class="entry__price">{price} {currency}</span>
    </span>
  </div>
</script>

CSS

.entry-list__loading,
.entry-list__empty
{
  display: none;
}
.entry-list__loading_processing,
.entry-list__empty_empty.entry-list__empty_ready
{
  display: block;
}

.entry
{
  padding: 5px;
  border-bottom: 1px solid #DDD;
  overflow: hidden;
}
.entry:hover
{
  background: #F0F0F0;
}
.entry IMG
{
  float: left;
  margin-right: 15px;
}
.entry__description
{
  overflow: hidden;
}
.entry__name
{
  display: block;
  font-size: 25px;
}
.entry__price
{
  font-size: 35px;
  color: #AA9988;
}

JavaScript

basis.require('basis.entity');
basis.require('basis.net.service');
basis.require('basis.net.jsonp');
basis.require('basis.ui');

// Сервис для работы с iTunes
var iTunesService = new basis.net.service.Service({
  transportClass: basis.net.jsonp.Transport // работаем по JSONP
  // тут могут быть общие настройки для все транспортов/запросов
});

//
// Тип сущность iTunes
//
var ITunesEntry = basis.entity.createType('ITunesEntry', {
  trackName: String,
  artworkUrl100: String,
  trackPrice: Number,
  releaseDate: String,
  country: String,
  currency: String
});

//
// Функция для получения набора с результами
// используется кеш
//
ITunesEntry.byFilters = (function(){
  var keys = ['entity', 'media', 'country', 'term'];
  var cache = {};

  // класс для создания наборов с результатами
  var SearchResults = basis.data.Dataset.subclass({
    syncAction: iTunesService.createAction({
      request: function(){
        return {
          url: 'https://itunes.apple.com/search?limit=100&' + this.params
        };
      },
      success: function(data){
        this.set(data.results.map(ITunesEntry.reader).map(ITunesEntry));
      }
    })
  });

  // генерация строки с параметрами по переданному объекту
  function getParams(data){
    var params = [];

    for (var i = 0, key; key = keys[i]; i++)
    {
      var value = data[key];

      if (typeof value == 'string')
        value = value.trim();

      if (value != null && value !== '')
        params.push(key + '=' + value);
    }

    return params.join('&');
  }

  return function(filters){
    if (!filters || !filters.term)
      return null;

    var params = getParams(filters);

    if (params in cache == false)
      // если набора с переданными параметрами еще нет, создаем его
      // и добавляем в кеш
      cache[params] = new SearchResults({
        filters: filters,
        params: params
      });

    return cache[params];
  };
})();

//
// Создаем классы полей (по сути компоненты)
//

// абстрактное поле,...