|
/*=== Suggested JS window width for readability (this is one line) ===*/ |
|
|
|
// data - example friends |
|
let friends = [ |
|
{name: 'Joe', age: 11, job: 'programmer'}, |
|
{name: 'Ali', age: 14, job: 'student'}, |
|
{name: 'Jil', age: 15, job: 'programmer'}, |
|
{name: 'Art', age: 16, job: 'student'}, |
|
{name: 'Phi', age: 36, job: 'manager'}, |
|
{name: 'Pat', age: 55, job: 'programmer'} |
|
]; |
|
|
|
// Mini-dom functions |
|
// Curry a generic element by attribute getter |
|
let getElementsByAttribute = R.curry(function (attr, val) { |
|
return Array.prototype.slice.call( |
|
document.querySelectorAll('['+attr+'="'+val+'"]') |
|
); |
|
}); |
|
// partially apply for different element types (name and type) |
|
let getElementsByName = getElementsByAttribute('name'); |
|
let getElementsByType = getElementsByAttribute('type'); |
|
// element value getters |
|
let getTextValue = el => el.value; |
|
let getCheckboxChecked = el => ({name:el.value, checked:el.checked}); |
|
// Curry a generic value getter |
|
let getInputValues = R.curry(function (typ, els) { |
|
return els.map(el => typ(el)); |
|
}); |
|
// partially apply to use different value getters |
|
let getTextInputValues = getInputValues(getTextValue); |
|
let getCheckboxInputValues = getInputValues(getCheckboxChecked); |
|
|
|
// View stuff |
|
// Get dom elements |
|
let messageBox = getElementsByName('message'); |
|
let filterBoxes = getElementsByName('filters[]'); |
|
let submitButton = getElementsByType('submit').pop(); |
|
// Get info from dom elements |
|
let getMessage = function () { |
|
return getTextInputValues(messageBox).pop(); |
|
}; |
|
let getFilters = function () { |
|
return getCheckboxInputValues(filterBoxes). |
|
reduce(function (filters, box) { |
|
if (box.checked) { |
|
if (box.name === 'teens') { |
|
filters.push(isTeenFriend); |
|
} else if (box.name === 'oddAges') { |
|
filters.push(isOddAgeFriend); |
|
} else if (box.name === 'programmers') { |
|
filters.push(isProgrammerFriend); |
|
} |
|
} |
|
return filters; |
|
}, []); |
|
}; |
|
// Attach dom listener for form |
|
document.querySelector('form').addEventListener('submit', |
|
function (e) { |
|
e.preventDefault(); |
|
shareFriends(getMessage()); |
|
} |
|
); |
|
|
|
// Program logic |
|
// Potential filters |
|
// Number filters |
|
// isNumber -> Number.isInteger |
|
let isTeen = num => num >= 13 && num <= 19; |
|
let isOdd = num => num % 2 === 1; |
|
// Programmer filter |
|
let isProgrammer = job => job === 'programmer'; |
|
// Curry and then partially apply to get filters for friends |
|
let validAttribute = R.curry((attr, tester, friend) => tester(friend[attr])); |
|
let validAgeFilter = validAttribute('age'); |
|
let isTeenFriend = validAgeFilter(isTeen); |
|
let isOddAgeFriend = validAgeFilter(isOdd); |
|
let isProgrammerFriend = validAttribute('job', isProgrammer); |
|
// Curry a composer of filters |
|
let validFriendByAllFilters = R.curry(function (filters, friend) { |
|
return R.allPass(filters)(friend); |
|
}); |
|
// Curry a share function |
|
let share = R.curry(function (friends, message) { |
|
// partially apply to get an array of filters to run friends through |
|
var filters = validFriendByAllFilters(getFilters()); |
|
// do the filtering and send the message |
|
friends.filter(filters). |
|
forEach(function (friend) { |
|
console.log(friend.name + ': ' + message); |
|
}); |
|
console.log(help); |
|
}); |
|
// partially apply the share function (could be more groups in the future?) |
|
let shareFriends = share(friends); |
|
|
|
// debug and testing |
|
let help = '--Call showFriends() in the console to see friend data--'; |
|
function showFriends() { |
|
friends.forEach(function (friend) { |
|
console.log(JSON.stringify(friend)); |
|
}); |
|
return help; |
|
}; |
|
console.log(help); |