JSFiddle - React, Tailwind, and code Playground

by SecretDeveloper

HTML

<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<script src="http://documentcloud.github.com/underscore/underscore-min.js"></script>
<div id="container">
    <div>
        <input id="txtSearch" type="text" data-bind="value:searchInput" />
        <input id="btnSearch" type="button" data-bind="click:search" value="Search Books" />
    </div>
    <ul data-bind="foreach:items">
        <li><a data-bind="attr: { href: link, title: description}, text: title"></a>
            <br/><span data-bind="text:description" />
        </li>
    </ul>
</div>

JavaScript

function validator(message, fun){
    var f = function(){
        return fun.apply(fun, arguments);
    };
    f['message'] = message;
    return f;
};

function checker(){
    var validators = _.toArray(arguments);
    return function(obj){
        return _.reduce(validators, function(errs, check){
            if(check(obj))
                return errs;
            else
                return _.chain(errs).push(check.message).value();                
        }, []);
    };
};

function isValidResourceItem(){
    var validators = checker(
  validator('obj can not be nul',function(obj){return !_.isNull(obj);}),
  validator('obj must contain title',function(obj){return !_.isNull(obj.title);}),
  validator('obj must contain canonicalVolumeLink',function(obj){return !_.isNull(obj.canonicalVolumeLink);}),
  validator('obj must contain description',function(obj){return !_.isNull(obj.description);})
                           );
        return validators;
};



$(document).ready(function () {
    
    function resultItem(title, link, description) {
        var self = this;
        self.title = ko.observable(title);
        self.link = ko.observable(link);
        self.description = ko.observable(description);
    }

    function viewModel() {
        var self = this;

        self.searchInput = ko.observable("G.R.R. Martin");
        self.items = ko.observableArray();

        self.mapResults = function (data) {
            var chk = isValidResourceItem();
            _.each(data.items, function (item) {
                
                var chkResult = chk(item.volumeInfo);
                if(chkResult.length == 0){                
                    var resultI = new resultItem(item.volumeInfo.title,
                                             item.volumeInfo.canonicalVolumeLink,
                                             item.volumeInfo.description);
                    self.items.push(resultI); // add to our observable array
                }
               ...