September Morn Update
This commit is contained in:
parent
4e2d22a71d
commit
aac6731f2c
6856 changed files with 141342 additions and 21127 deletions
|
|
@ -1,67 +1,206 @@
|
|||
(function (lngCols, lngRows) {
|
||||
(() => {
|
||||
'use strict';
|
||||
|
||||
//range(5, 20) --> [5..20]
|
||||
//range('a', 'n') --> ['a'..'n']
|
||||
function range(m, n) {
|
||||
var blnAlpha = typeof m === 'string',
|
||||
iFirst = blnAlpha ? m.charCodeAt(0) : m,
|
||||
lstInt = Array.apply(
|
||||
null,
|
||||
Array((blnAlpha ? n.charCodeAt(0) : n) - iFirst + 1)
|
||||
).map(function (x, i) {
|
||||
return iFirst + i;
|
||||
});
|
||||
// HTML ---------------------------------------------
|
||||
|
||||
return blnAlpha ? lstInt.map(
|
||||
function (x) {
|
||||
return String.fromCharCode(x);
|
||||
}
|
||||
) : lstInt;
|
||||
}
|
||||
// treeHTML :: tree
|
||||
// {tag :: String, text :: String, kvs :: Dict}
|
||||
// -> String
|
||||
const treeHTML = tree =>
|
||||
foldTree(
|
||||
(x, xs) => `<${x.tag + attribString(x.kvs)}>` + (
|
||||
'text' in x ? (
|
||||
x.text
|
||||
) : '\n'
|
||||
) + concat(xs) + `</${x.tag}>\n`)(
|
||||
tree
|
||||
);
|
||||
|
||||
// Letter label for first column (last column will be 'Z')
|
||||
var strFirstCol = String.fromCharCode('Z'.charCodeAt(0) - (lngCols - 1));
|
||||
// attribString :: Dict -> String
|
||||
const attribString = dct =>
|
||||
dct ? (
|
||||
' ' + Object.keys(dct)
|
||||
.reduce(
|
||||
(a, k) => a + k + '="' + dct[k] + '" ', ''
|
||||
).trim()
|
||||
) : '';
|
||||
|
||||
var lstData = [[''].concat(range(strFirstCol, 'Z'))].concat(
|
||||
range(1, lngRows).map(
|
||||
function (row) {
|
||||
return [row].concat(
|
||||
range(1, lngCols).map(
|
||||
function () {
|
||||
return Math.floor(
|
||||
Math.random() * 9999
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
// TEST ---------------------------------------------
|
||||
const main = () => {
|
||||
const
|
||||
tableStyle = {
|
||||
style: "width:25%; border:2px solid silver;"
|
||||
},
|
||||
trStyle = {
|
||||
style: "border:1px solid silver;text-align:right;"
|
||||
},
|
||||
strCaption = 'Table generated by JS';
|
||||
|
||||
const
|
||||
n = 3,
|
||||
colNames = take(n)(enumFrom('A')),
|
||||
dataRows = map(
|
||||
x => Tuple(x)(map(randomRInt(100)(9999))(
|
||||
colNames
|
||||
)))(take(n)(enumFrom(1)));
|
||||
|
||||
const
|
||||
// TABLE AS TREE STRUCTURE -----------------
|
||||
tableTree = Node({
|
||||
tag: 'table',
|
||||
kvs: tableStyle
|
||||
},
|
||||
append([
|
||||
Node({
|
||||
tag: 'caption',
|
||||
text: 'Table source generated by JS'
|
||||
}),
|
||||
// HEADER ROW -----------------------
|
||||
Node({
|
||||
tag: 'tr',
|
||||
},
|
||||
map(k => Node({
|
||||
tag: 'th',
|
||||
kvs: {
|
||||
style: "text-align:right;"
|
||||
},
|
||||
text: k
|
||||
}))(cons('')(colNames))
|
||||
)
|
||||
// DATA ROWS ------------------------
|
||||
])(map(tpl => Node({
|
||||
tag: 'tr',
|
||||
kvs: trStyle
|
||||
}, cons(
|
||||
Node({
|
||||
tag: 'th',
|
||||
text: fst(tpl)
|
||||
}))(
|
||||
map(v => Node({
|
||||
tag: 'td',
|
||||
text: v.toString()
|
||||
}))(snd(tpl))
|
||||
)))(dataRows))
|
||||
);
|
||||
|
||||
// Return a value and/or apply console.log to it.
|
||||
// (JS embeddings vary in their IO channels)
|
||||
const strHTML = treeHTML(tableTree);
|
||||
return (
|
||||
console.log(strHTML)
|
||||
//strHTML
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// GENERIC FUNCTIONS --------------------------------
|
||||
|
||||
// Node :: a -> [Tree a] -> Tree a
|
||||
const Node = (v, xs) => ({
|
||||
type: 'Node',
|
||||
root: v,
|
||||
nest: xs || []
|
||||
});
|
||||
|
||||
// Tuple (,) :: a -> b -> (a, b)
|
||||
const Tuple = a => b => ({
|
||||
type: 'Tuple',
|
||||
'0': a,
|
||||
'1': b,
|
||||
length: 2
|
||||
});
|
||||
|
||||
// append (++) :: [a] -> [a] -> [a]
|
||||
// append (++) :: String -> String -> String
|
||||
const append = xs => ys => xs.concat(ys);
|
||||
|
||||
// chr :: Int -> Char
|
||||
const chr = String.fromCodePoint;
|
||||
|
||||
// concat :: [[a]] -> [a]
|
||||
// concat :: [String] -> String
|
||||
const concat = xs =>
|
||||
0 < xs.length ? (() => {
|
||||
const unit = 'string' !== typeof xs[0] ? (
|
||||
[]
|
||||
) : '';
|
||||
return unit.concat.apply(unit, xs);
|
||||
})() : [];
|
||||
|
||||
// cons :: a -> [a] -> [a]
|
||||
const cons = x => xs => [x].concat(xs);
|
||||
|
||||
// enumFrom :: a -> [a]
|
||||
function* enumFrom(x) {
|
||||
let v = x;
|
||||
while (true) {
|
||||
yield v;
|
||||
v = succ(v);
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
'<table>',
|
||||
// enumFromToChar :: Char -> Char -> [Char]
|
||||
const enumFromToChar = m => n => {
|
||||
const [intM, intN] = [m, n].map(
|
||||
x => x.charCodeAt(0)
|
||||
);
|
||||
return Array.from({
|
||||
length: Math.floor(intN - intM) + 1
|
||||
}, (_, i) => String.fromCodePoint(intM + i));
|
||||
};
|
||||
|
||||
' <thead style = "text-align: right;">',
|
||||
' ' + lstData[0].reduce(
|
||||
function (a, s) {
|
||||
return a + '<th>' + s + '</th>';
|
||||
}, '<tr>'
|
||||
) + '</tr>',
|
||||
' </thead>',
|
||||
// foldTree :: (a -> [b] -> b) -> Tree a -> b
|
||||
const foldTree = f => tree => {
|
||||
const go = node =>
|
||||
f(node.root, node.nest.map(go));
|
||||
return go(tree);
|
||||
};
|
||||
|
||||
' <tbody style = "text-align: right;">',
|
||||
lstData.slice(1).map(
|
||||
function (row) {
|
||||
return ' ' + row.reduce(
|
||||
function (a, s) {
|
||||
return a + '<td>' + s + '</td>';
|
||||
}, '<tr>'
|
||||
) + '</tr>';
|
||||
}
|
||||
).join('\n'),
|
||||
' </tbody>',
|
||||
// fst :: (a, b) -> a
|
||||
const fst = tpl => tpl[0];
|
||||
|
||||
'</table>'
|
||||
].join('\n');
|
||||
// isChar :: a -> Bool
|
||||
const isChar = x =>
|
||||
('string' === typeof x) && (1 === x.length);
|
||||
|
||||
})(3, 4); // (3 columns --> [X..Z]), (4 rows --> [1..4])
|
||||
// map :: (a -> b) -> [a] -> [b]
|
||||
const map = f => xs =>
|
||||
(Array.isArray(xs) ? (
|
||||
xs
|
||||
) : xs.split('')).map(f);
|
||||
|
||||
// ord :: Char -> Int
|
||||
const ord = c => c.codePointAt(0);
|
||||
|
||||
// randomRInt :: Int -> Int -> () -> Int
|
||||
const randomRInt = low => high => () =>
|
||||
low + Math.floor(
|
||||
(Math.random() * ((high - low) + 1))
|
||||
);
|
||||
|
||||
// snd :: (a, b) -> b
|
||||
const snd = tpl => tpl[1];
|
||||
|
||||
// succ :: Enum a => a -> a
|
||||
const succ = x =>
|
||||
isChar(x) ? (
|
||||
chr(1 + ord(x))
|
||||
) : isNaN(x) ? (
|
||||
undefined
|
||||
) : 1 + x;
|
||||
|
||||
// take :: Int -> [a] -> [a]
|
||||
// take :: Int -> String -> String
|
||||
const take = n => xs =>
|
||||
'GeneratorFunction' !== xs.constructor.constructor.name ? (
|
||||
xs.slice(0, n)
|
||||
) : [].concat.apply([], Array.from({
|
||||
length: n
|
||||
}, () => {
|
||||
const x = xs.next();
|
||||
return x.done ? [] : [x.value];
|
||||
}));
|
||||
|
||||
// MAIN ---
|
||||
return main();
|
||||
})();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue