2021-03-23 14:15:21 -04:00
|
|
|
<script>
|
|
|
|
let Node = {
|
|
|
|
Create:(inID, inDisplay, inChildren)=>
|
|
|
|
{
|
|
|
|
let node = {
|
|
|
|
ID:inID,
|
|
|
|
Display:inDisplay,
|
|
|
|
Active:false,
|
|
|
|
Highlighted:0,
|
|
|
|
Parent:false,
|
|
|
|
Children:inChildren,
|
|
|
|
Leaves:[]
|
|
|
|
};
|
|
|
|
if(inChildren)
|
|
|
|
{
|
|
|
|
inChildren.forEach(c=>c.Parent = node);
|
|
|
|
}
|
|
|
|
return node;
|
|
|
|
},
|
|
|
|
Path:(inNode, inList) =>
|
|
|
|
{
|
|
|
|
let node = inNode;
|
|
|
|
while(node)
|
|
|
|
{
|
|
|
|
inList.push(node);
|
|
|
|
node = node.Parent;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Leaves:(inNode, inList) =>
|
|
|
|
{
|
|
|
|
var i;
|
|
|
|
var child;
|
|
|
|
if(inNode.Children)
|
|
|
|
{
|
|
|
|
for(i=0; i<inNode.Children.length; i++)
|
|
|
|
{
|
|
|
|
Node.Decedents(inNode.Children[i], inList);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
inList.push(inNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
|
2021-03-18 14:03:57 -04:00
|
|
|
<div id="root"></div>
|
|
|
|
<script type="module">
|
2021-03-19 17:09:38 -04:00
|
|
|
|
2021-03-18 14:03:57 -04:00
|
|
|
import _ from "https://dev.jspm.io/lodash";
|
|
|
|
import React from "https://dev.jspm.io/react/index.js";
|
|
|
|
import ReactDOM from "https://dev.jspm.io/react-dom/index.js";
|
|
|
|
import ReactDOMServer from "https://dev.jspm.io/react-dom/server.js";
|
2021-03-19 17:09:38 -04:00
|
|
|
|
|
|
|
let Util = {
|
|
|
|
ParsePassage:inRef=>
|
|
|
|
{
|
|
|
|
let indexNumeric = inRef.lastIndexOf(" ");
|
|
|
|
let partBook = inRef.substring(0, indexNumeric);
|
|
|
|
let chapterVerse = inRef.substring(indexNumeric+1).split(":");
|
|
|
|
return [partBook, chapterVerse[0], chapterVerse[1]];
|
|
|
|
}
|
|
|
|
};
|
2021-03-23 14:15:21 -04:00
|
|
|
|
2021-03-18 14:03:57 -04:00
|
|
|
let h = React.createElement;
|
|
|
|
|
|
|
|
let ElemApp = props =>
|
|
|
|
{
|
|
|
|
return h("div", null,
|
|
|
|
[
|
2021-03-23 14:15:21 -04:00
|
|
|
h(ElemTreeNode, {key:"tree", node:App.State.Tree.Root}),
|
2021-03-18 14:03:57 -04:00
|
|
|
h("h4", {key:0}, "topics"),
|
|
|
|
h(ElemTopics, {key:1}),
|
|
|
|
h(ElemItems, {key:3})
|
|
|
|
]
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
let ElemItems = props =>
|
|
|
|
{
|
2021-03-19 17:09:38 -04:00
|
|
|
let list = App.State.Pages.All[App.State.Pages.Active].map( i=>h(ElemItem, {...i, key:i.id} ) );
|
|
|
|
|
|
|
|
let pages = h(ElemPager, {count:App.State.Pages.All.length, active:App.State.Pages.Active}, null);
|
|
|
|
|
|
|
|
return h("div", null, [
|
|
|
|
h("h4", {key:0}, App.State.Items.Active.length+" results"),
|
|
|
|
h("div", {key:1}, pages),
|
|
|
|
h("div", {key:2}, list),
|
|
|
|
h("div", {key:3}, pages)
|
|
|
|
]);
|
2021-03-18 14:03:57 -04:00
|
|
|
}
|
|
|
|
let ElemItem = props =>
|
|
|
|
{
|
|
|
|
return h("div", {key:0}, [
|
2021-03-19 17:09:38 -04:00
|
|
|
h("div", {key:1},
|
|
|
|
[
|
|
|
|
h("span", {key:0}, props.title),
|
|
|
|
h("em", {key:1}, props.id)
|
|
|
|
]
|
|
|
|
),
|
2021-03-18 14:03:57 -04:00
|
|
|
h("small", {key:3}, props.bible)
|
|
|
|
])
|
|
|
|
};
|
2021-03-19 17:09:38 -04:00
|
|
|
let ElemPager = ({count, active}) =>
|
|
|
|
{
|
|
|
|
var children;
|
|
|
|
var blockIntro, blockAt, blockOutro;
|
|
|
|
var hitLeft, hitRight;
|
|
|
|
|
|
|
|
let renderRange = (inStart, inStop) =>
|
|
|
|
{
|
|
|
|
let output = [];
|
|
|
|
for(let i=inStart; i<=inStop; i++)
|
|
|
|
{
|
2021-03-22 10:31:35 -04:00
|
|
|
output.push(h("button", {key:i, onClick:e=>App.Update.Page(i)}, i+1));
|
2021-03-19 17:09:38 -04:00
|
|
|
}
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
let renderSpacer = () => h("span", {key:Math.random()}, "…");
|
|
|
|
|
|
|
|
|
|
|
|
blockIntro = [0, 1, 2];
|
|
|
|
blockAt = [active-1, active, active+1];
|
|
|
|
blockOutro = [count-3, count-2, count-1];
|
|
|
|
|
|
|
|
hitLeft = _.last(blockIntro) >= _.head(blockAt);
|
|
|
|
hitRight = _.last(blockAt) >= _.head(blockOutro);
|
|
|
|
|
|
|
|
if(count < 2)
|
|
|
|
{
|
|
|
|
children = [];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if( (hitLeft && hitRight) || count < 7)
|
|
|
|
{
|
2021-03-22 10:31:35 -04:00
|
|
|
children = renderRange(_.head(blockIntro), _.last(blockOutro)) /* merge all */
|
2021-03-19 17:09:38 -04:00
|
|
|
}
|
|
|
|
else if(!hitLeft && hitRight)
|
|
|
|
{
|
|
|
|
children = [
|
|
|
|
...renderRange(_.head(blockIntro), _.last(blockIntro)),
|
|
|
|
renderSpacer(),
|
|
|
|
...renderRange(Math.min(_.head(blockAt), _.head(blockOutro)), _.last(blockOutro)) /* merge end */
|
|
|
|
];
|
|
|
|
}
|
|
|
|
else if(hitLeft && !hitRight)
|
|
|
|
{
|
|
|
|
children = [
|
|
|
|
...renderRange(_.head(blockIntro), Math.max(_.last(blockAt), _.last(blockIntro)) ), /* merge beginning */
|
|
|
|
renderSpacer(),
|
|
|
|
...renderRange(_.head(blockOutro), _.last(blockOutro))
|
|
|
|
];
|
|
|
|
}
|
|
|
|
else if(!hitLeft && !hitRight)
|
|
|
|
{
|
|
|
|
children = [
|
|
|
|
...renderRange(_.head(blockIntro), _.last(blockIntro)),
|
|
|
|
renderSpacer(),
|
|
|
|
...renderRange(_.head(blockAt), _.last(blockAt)),
|
|
|
|
renderSpacer(),
|
|
|
|
...renderRange(_.head(blockOutro), _.last(blockOutro))
|
|
|
|
];
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return h("div", {}, children);
|
|
|
|
};
|
2021-03-18 14:03:57 -04:00
|
|
|
|
|
|
|
let ElemTopics = props =>
|
|
|
|
{
|
|
|
|
let children = App.State.Topics.All.map( t=>
|
|
|
|
{
|
|
|
|
return h(ElemTopic, {
|
2021-03-22 10:31:35 -04:00
|
|
|
onClick:e=>App.Update.Topic(t),
|
2021-03-18 14:03:57 -04:00
|
|
|
key:t.id,
|
|
|
|
label:t.display,
|
|
|
|
active:t.active
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return h("div", null, children);
|
|
|
|
};
|
|
|
|
let ElemTopic = props =>
|
|
|
|
{
|
|
|
|
let label = props.active? props.label+" !" : props.label;
|
|
|
|
return h("button", {onClick:props.onClick}, label);
|
|
|
|
};
|
|
|
|
|
2021-03-23 14:15:21 -04:00
|
|
|
let ElemTreeNode = ({node}) =>
|
|
|
|
{
|
|
|
|
let children = [];
|
|
|
|
if(node.Children)
|
|
|
|
{
|
|
|
|
children = node.Children.map( c=>h(ElemTreeNode, {node:c, key:c.ID}));
|
|
|
|
}
|
|
|
|
|
|
|
|
return h("div", {style:{padding:"10px"}}, [
|
|
|
|
h("strong", {
|
|
|
|
onClick:e=>
|
|
|
|
{
|
|
|
|
e.stopPropagation();
|
|
|
|
App.Update.Select(App.State.Tree, node);
|
|
|
|
},
|
|
|
|
style:
|
|
|
|
{
|
|
|
|
background:node.Highlighted?"red":"none"
|
|
|
|
}
|
|
|
|
}, node.Display),
|
|
|
|
h("div", {}, children)
|
|
|
|
]);
|
|
|
|
};
|
|
|
|
|
2021-03-18 14:03:57 -04:00
|
|
|
var App = {
|
|
|
|
State:
|
|
|
|
{
|
|
|
|
Items:
|
|
|
|
{
|
|
|
|
All:[],
|
|
|
|
Active:[]
|
|
|
|
},
|
2021-03-19 17:09:38 -04:00
|
|
|
Pages:
|
|
|
|
{
|
|
|
|
All:[],
|
|
|
|
Active:0,
|
|
|
|
},
|
2021-03-23 14:15:21 -04:00
|
|
|
Tree:
|
|
|
|
{
|
|
|
|
Active:false,
|
|
|
|
Highlighted:false,
|
|
|
|
Root:
|
|
|
|
Node.Create("root", "Root", [
|
|
|
|
Node.Create("b1", "Branch 1", [
|
|
|
|
Node.Create("l1", "Leaf One")
|
|
|
|
]),
|
|
|
|
Node.Create("b2", "Branch 2", [
|
|
|
|
Node.Create("l2", "Leaf Two"),
|
|
|
|
Node.Create("l3", "Leaf Three"),
|
|
|
|
])
|
|
|
|
])
|
|
|
|
},
|
2021-03-18 14:03:57 -04:00
|
|
|
Topics:
|
|
|
|
{
|
|
|
|
All:
|
|
|
|
[
|
|
|
|
{
|
|
|
|
id:"gospel-the",
|
|
|
|
display:"The Gospel",
|
2021-03-19 17:09:38 -04:00
|
|
|
active:false,
|
|
|
|
members:[]
|
2021-03-18 14:03:57 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
id:"jesus-christ",
|
|
|
|
display:"Jesus Christ",
|
2021-03-19 17:09:38 -04:00
|
|
|
active:false,
|
|
|
|
members:[]
|
2021-03-18 14:03:57 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
id:"biblical-figures",
|
|
|
|
display:"Biblical Figures",
|
2021-03-19 17:09:38 -04:00
|
|
|
active:false,
|
|
|
|
members:[]
|
2021-03-18 14:03:57 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
id:"free-will",
|
|
|
|
display:"Free Will",
|
2021-03-19 17:09:38 -04:00
|
|
|
active:false,
|
|
|
|
members:[]
|
2021-03-18 14:03:57 -04:00
|
|
|
},
|
|
|
|
{
|
|
|
|
id:"secular-culture",
|
|
|
|
display:"Secular Culture",
|
2021-03-19 17:09:38 -04:00
|
|
|
active:false,
|
|
|
|
members:[]
|
2021-03-18 14:03:57 -04:00
|
|
|
}
|
|
|
|
],
|
|
|
|
Active:[]
|
|
|
|
},
|
|
|
|
Scripture:
|
|
|
|
{
|
|
|
|
All:{},
|
|
|
|
Active:[]
|
|
|
|
}
|
|
|
|
},
|
2021-03-23 14:15:21 -04:00
|
|
|
|
2021-03-18 14:03:57 -04:00
|
|
|
RootDOM:document.querySelector("#root"),
|
|
|
|
RootComponent:ElemApp,
|
|
|
|
Render:()=>ReactDOM.render( h(App.RootComponent), App.RootDOM ),
|
|
|
|
ApplyFilters:()=>
|
|
|
|
{
|
|
|
|
if(App.State.Topics.Active.length == 0)
|
2021-03-17 15:43:19 -04:00
|
|
|
{
|
2021-03-18 14:03:57 -04:00
|
|
|
App.State.Items.Active = [...App.State.Items.All];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
App.State.Items.Active = App.State.Items.All.filter( item =>
|
|
|
|
{
|
|
|
|
for(let i=0; i<item.topics.length; i++)
|
|
|
|
{
|
|
|
|
for(let j=0; j<App.State.Topics.Active.length; j++)
|
|
|
|
{
|
|
|
|
if(item.topics[i] == App.State.Topics.Active[j].id)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2021-03-17 15:43:19 -04:00
|
|
|
});
|
2021-03-18 14:03:57 -04:00
|
|
|
}
|
2021-03-19 17:09:38 -04:00
|
|
|
App.State.Pages.All = _.chunk(App.State.Items.Active, 10);
|
|
|
|
App.State.Pages.Active = 0;
|
2021-03-18 14:03:57 -04:00
|
|
|
},
|
2021-03-23 14:15:21 -04:00
|
|
|
|
2021-03-22 10:31:35 -04:00
|
|
|
Update:
|
2021-03-18 14:03:57 -04:00
|
|
|
{
|
2021-03-23 14:15:21 -04:00
|
|
|
Select:(inTree, inNode)=>
|
|
|
|
{
|
|
|
|
if(inNode.Active)
|
|
|
|
{
|
|
|
|
inNode.Active = false;
|
|
|
|
inTree.Highlighted.forEach( h=>h.Highlighted-- );
|
|
|
|
|
|
|
|
inTree.Root.Active = true;
|
|
|
|
inTree.Root.Highlighted = true;
|
|
|
|
|
|
|
|
inTree.Active = inTree.Root;
|
|
|
|
inTree.Highlighted = [inTree.Root];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(inTree.Active)
|
|
|
|
{
|
|
|
|
inTree.Active.Active = false;
|
|
|
|
inTree.Highlighted.forEach( h=>h.Highlighted-- );
|
|
|
|
}
|
|
|
|
|
|
|
|
inTree.Active = inNode;
|
|
|
|
inTree.Active.Active = true;
|
|
|
|
inTree.Highlighted = [];
|
|
|
|
Node.Path(inTree.Active, inTree.Highlighted);
|
|
|
|
inTree.Highlighted.forEach( h=>h.Highlighted++ );
|
|
|
|
}
|
|
|
|
console.log(inTree);
|
|
|
|
App.Render();
|
|
|
|
},
|
2021-03-22 10:31:35 -04:00
|
|
|
Load:(file)=>
|
2021-03-18 14:03:57 -04:00
|
|
|
{
|
2021-03-22 10:31:35 -04:00
|
|
|
fetch(file)
|
|
|
|
.then(inAccept=>inAccept.text())
|
|
|
|
.then(inAccept=>
|
|
|
|
{
|
|
|
|
let columns = inAccept.split("|");
|
|
|
|
App.State.Items.All = [];
|
|
|
|
for(let i=0; i<columns.length; i+=4)
|
2021-03-18 14:03:57 -04:00
|
|
|
{
|
2021-03-22 10:31:35 -04:00
|
|
|
let row = Math.floor(i/4);
|
|
|
|
App.State.Items.All[row] = {
|
|
|
|
title:columns[i+0],
|
|
|
|
id:columns[i+1],
|
|
|
|
bible:columns[i+2].split("*"),
|
|
|
|
topics:columns[i+3].split("*")
|
|
|
|
};
|
2021-03-18 14:03:57 -04:00
|
|
|
}
|
|
|
|
App.ApplyFilters();
|
|
|
|
App.Render();
|
2021-03-22 10:31:35 -04:00
|
|
|
}
|
|
|
|
);
|
|
|
|
},
|
|
|
|
Topic:(topic)=>
|
|
|
|
{
|
|
|
|
if(topic.active)
|
|
|
|
{
|
|
|
|
topic.active = false;
|
|
|
|
App.State.Topics.Active = App.State.Topics.Active.filter( t=>t.id != topic.id );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
topic.active = true;
|
|
|
|
App.State.Topics.Active.push(topic);
|
|
|
|
}
|
|
|
|
App.ApplyFilters();
|
|
|
|
App.Render();
|
|
|
|
},
|
|
|
|
Page:(page)=>
|
|
|
|
{
|
|
|
|
if(page !== false)
|
|
|
|
{
|
|
|
|
App.State.Pages.Active = page;
|
|
|
|
App.Render();
|
2021-03-18 14:03:57 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-22 10:31:35 -04:00
|
|
|
App.Update.Load("data-flat.csv");
|
2021-03-18 14:03:57 -04:00
|
|
|
|
2021-03-17 15:43:19 -04:00
|
|
|
</script>
|