Demo Part 4
Now we want to display the videos from the returned list from the AJAX call.
/* global define */
define([
...
], function($, _, P, Maybe, Player, bacon, http) {
'use strict';
io.extendFn()
// HELPERS ///////////////////////////////////////////////////////////////////////////
var compose = P.compose;
..
// PURE //////////////////////////////////////////////////////////////////////////////
var listen = _.curry(function (type, elt) {
return Bacon.fromEventTarget(elt, type)
})
var getDom = $.toIO()
var keypressStream = listen('keyup')
// eventValue :: DomEvent -> String
var eventValue = compose(_.get('value')), _.get('target'))
// valueStream :: Dom -> EventStream String
var valueStream = compose(map(eventValue), keypressStream)
// termUrl :: String -> URL
var termUrl = function (term) {
return "http://gdata.youtube.com/feeds/api/videos?" +
$.param({q:term, alt: 'json'})
}
// urlStream :: Dom -> EventStream URL (String)
var urlStream = compose(map(termUrl, valueStream))
// search :: String -> Future JSON
var searchStream = comose(map(http.getJSON), urlStream)
// **** 2.
// entryToLi :: Entry -> Dom
var entryToLi = function (elt) {
// practical to construct it with jQuery...
// adding the attributes is easier with jQuery
return $("<li />", { 'data-youtubeid': elt.id.$t, text: elt.title.$t })
}
// **** 1.
// videoUrls :: JSON -> [URL]
// getting the values from the JSON
// the JSON uses "$t" for the entry id value property name!!
var videoUrls = compose(map(getEntryUrl), _.get('entry'), _.get('feed'))
// **** 4.
var liStream = compose(map(resultToHtml), searchStream)
// IMPURE ////////////////////////////////////////////////////////////////////////////
// **** 3. log out again
// set the right side of the of fork to setHTML("#results")
getDom('#search').map(searchStream).runIO().onValue(fork(log, setHTML("#results")))
});
We need to get the entry.id
property from the JSON response.
(They're basically writing Haskell. Verbose Haskell)
At step #4 above, they decide it's better to go through the diffs of the GIT repo rather than debugging the app step by step. (time: -2.34)
The final app.js from the repo:
/* global define */
define([
..
], function($, _, P, Maybe, Player, io, bacon, http) {
'use strict';
io.extendFn();
// HELPERS ///////////////////////////////////////////
var compose = P.compose;
var map = P.map;
var log = function(x) { console.log(x); return x; }
var fork = _.curry(function(f, future) { return future.fork(log, f); })
var setHtml = _.curry(function(sel, x) { return $(sel).html(x); });
var listen = _.curry(function (event, target) {
return bacon.fromEventTarget(target, event);
});
var getData = _.curry(function(name, elt) { return $(elt).data(name); });
var last = function(ar) { return ar[ar.length - 1]; };
// PURE //////////////////////////////////////////////////
// api_key :: String
var api_key = 'AIzaSyAWoa7aqds2Cx_drrrb5FPsRObFa7Dxkfg';
//+ eventValue :: DomEvent -> String
var eventValue = compose(_.get('value'), _.get('target'));
//+ valueStream :: DomEvent -> EventStream String
var valueStream = compose(map(eventValue), listen('keyup'));
//+ termToUrl :: String -> URL
var termToUrl = function(term) {
return 'https://www.googleapis.com/youtube/v3/search?' +
$.param({part: 'snippet', q: term, key: api_key});
};
//+ urlStream :: DomEvent -> EventStream String
var urlStream = compose(map(termToUrl), valueStream);
//+ getInputStream :: Selector -> IO EventStream String
var getInputStream = compose(map(urlStream), $.toIO());
//+ render :: Entry -> Dom
var render = function(e) {
return $('<li/>', {text: e.snippet.title, 'data-youtubeid': e.id.videoId});
};
//+ videoEntries :: YoutubeResponse -> [Dom]
var videoEntries = compose(map(render), _.get('items'));
//+ search :: URL -> Future [Dom]
var search = compose(map(videoEntries), http.getJSON);
//+ DomElement -> EventStream DomElement
var clickStream = compose(map(_.get('target')), listen('click'));
//+ URL -> String
var idInUrl = compose(last, _.split('/'));
//+ youtubeLink :: DomElement -> Maybe ID
var youtubeId = compose(map(idInUrl), Maybe, getData('youtubeid'));
// IMPURE /////////////////////////////////////////////////////
getInputStream('#search').runIO().onValue(
compose(fork(setHtml('#results')), search)
);
clickStream(document).onValue(
compose(map(compose(setHtml('#player'), Player.create)), youtubeId)
);
});