Skip to content

Instantly share code, notes, and snippets.

@rrag
Last active November 5, 2017 05:28
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rrag/9cb51ae670de20255dcc to your computer and use it in GitHub Desktop.
Save rrag/9cb51ae670de20255dcc to your computer and use it in GitHub Desktop.
An attempt at FRP using Ramda.js and Bacon.js
<!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>
(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