See this in action using plunker http://plnkr.co/edit/gist:9cb51ae670de20255dcc?p=preview
Last active
November 5, 2017 05:28
-
-
Save rrag/9cb51ae670de20255dcc to your computer and use it in GitHub Desktop.
An attempt at FRP using Ramda.js and Bacon.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>Bootswatch: Slate</title> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<!-- | |
<link rel="stylesheet" href="bootstrap/dist/css/bootstrap.min.css"> | |
<script type="text/javascript" src="jquery/dist/jquery.js"></script> | |
<script type="text/javascript" src="ramda/dist/ramda.js"></script> | |
<script type="text/javascript" src="baconjs/dist/Bacon.js"></script> --> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.17.1/ramda.js"></script> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bacon.js/0.7.70/Bacon.js"></script> | |
<style type="text/css"> | |
.fav { | |
background-color: rgb(92, 184, 92) !important; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="navbar navbar-default"> | |
<div class="container"> | |
<div class="navbar-header"> | |
</div> | |
</div> | |
</div> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-xs-6"> | |
<div class="well"> | |
<form class="form-horizontal"> | |
<legend>Github Repos, Search em</legend> | |
<fieldset> | |
<input type="text" class="form-control" id="queryRepo" placeholder="Search repositories" value="baconjs"> | |
</fieldset> | |
<span>All input is debounced by 500 ms. From <a href="https://developer.github.com/v3/search/#rate-limit">github docs</a> - For unauthenticated requests, the rate limit allows you to make up to 10 requests per minute.</span> | |
</form> | |
</div> | |
<div class="list-group"> | |
<h4 class="panel-heading">Search results</h4> | |
<div id="searchResults"> | |
<a href="#" class="list-group-item">Loading...</a> | |
</div> | |
</div> | |
</div> | |
<div class="col-xs-6"> | |
<div class="panel panel-default"> | |
<div class="panel-heading"> | |
<h3>Favorites here</h3> | |
</div> | |
</div> | |
<div class="list-group" id="store"> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script type="text/javascript" src="index.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(){ | |
var favouriteRepo = []; | |
var q = "https://api.github.com/search/repositories?q="; | |
var queryElement = document.getElementById("queryRepo"); | |
var loading = $("<a href=\"#\" class=\"list-group-item\">Loading...</a>"); | |
var noResults = R.always($("<a href=\"#\" class=\"list-group-item\">No Results Found</a>")); | |
function searchResultEntry(fav, repo) { | |
var className = "result-item list-group-item"; | |
var favorite = fav ? " fav" : ""; | |
return $("<a href=\"#\" id=" + repo.id | |
+ " class=\"" + className.concat(favorite) + "\">" | |
+ repo.full_name + " - " + repo.stargazers_count + " - stars </a>"); | |
} | |
function storedEntry(detail) { | |
return $("<a href=\"#\" class=\"list-group-item\">" + detail + "</a>"); | |
} | |
var log = R.curry(function (trace, debug) { | |
console.log(trace, " - ", debug); | |
return debug; | |
}); | |
var searchInProgress = Bacon.fromEvent(queryElement, "input") | |
.map(R.path(["target", "value"])) | |
.startWith(queryElement.value) | |
.filter(R.compose(R.lt(3), R.prop("length"))) | |
var searchCandidates = searchInProgress.debounce(500) | |
.skipDuplicates() | |
.flatMapLatest(R.compose(Bacon.fromPromise, $.ajax, R.concat(q))) | |
.map(R.prop("items")) | |
; | |
var formatResults = R.compose( | |
R.ifElse(R.pipe(R.length, R.equals(0)), noResults, R.identity), | |
// R.map(searchResultEntry.bind(null, false)), | |
R.map(R.ifElse( | |
function (item) { return R.contains(item.id, favouriteRepo); }, | |
searchResultEntry.bind(null, true), | |
searchResultEntry.bind(null, false) | |
))); | |
searchCandidates.onValue(function(results) { | |
// $("#searchResults").html("") | |
$("#searchResults").html(formatResults(results)); | |
}); | |
searchInProgress.onValue(function() { | |
$("#searchResults").html(loading); | |
}); | |
var toggleSelectResult = $("#searchResults").asEventStream("click") | |
.map(function (e) { e.preventDefault(); return e; }) | |
.map(R.prop("target")) | |
.filter(function (element) { return $(element).hasClass("result-item"); }) | |
.map(R.props(["id", "innerHTML"])) | |
.map(function (entry) { return { id: parseInt(entry[0]), innerHTML: entry[1] }; }) | |
.filter(function (entry) { return !R.contains(entry.id, favouriteRepo); }); | |
var favouriteRepoBus = new Bacon.Bus(); | |
favouriteRepoBus.plug(toggleSelectResult); | |
favouriteRepoBus | |
.onValue(function (value) { | |
favouriteRepo.push(parseInt(value.id, 10)) | |
$("#store").append(storedEntry(value.innerHTML)); | |
$("a#" + value.id).addClass("fav"); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment