ModeConnections.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. var m = require('mithril');
  2. // https://github.com/markdown-it/markdown-it
  3. var markdown = require('markdown-it')()
  4. .use(require('markdown-it-footnote'));
  5. var _dbs = require('./dbs');
  6. var _Header = require('./header');
  7. var _Footer = require('./footer');
  8. var _Ui = require('./ui.js');
  9. // ____ __
  10. // / __ \____ / /_
  11. // / / / / __ \/ __/
  12. // / /_/ / /_/ / /_
  13. // /_____/\____/\__/
  14. var _Dot = {
  15. id:null,
  16. dottype:null,
  17. type:'',
  18. title:'',
  19. text:'',
  20. summary:'',
  21. active:true,
  22. opened:false,
  23. links:null,
  24. parents:[],
  25. lang:_dbs.lang,
  26. setupTitle(vn){
  27. this.title = vn.attrs.title;
  28. if(!this.title){
  29. this.title = this.type;
  30. }
  31. this.title = markdown.renderInline(this.title);
  32. },
  33. setuptext(vn){
  34. // console.log('setuptext', vn);
  35. // construct text
  36. this.text = vn.attrs.text || '';
  37. this.rendered_text = markdown.render(this.text);
  38. if(this.dottype == "preface"){
  39. this.summary = this.rendered_text;
  40. }else{
  41. // construct summary
  42. // TODO: summary needs more work (strip tags, markdown render)
  43. // remove img
  44. this.summary = this.text.replace(/!\[[^\]]+\]\([^\)]+\)/g, "");
  45. // get portion of text
  46. this.summary = this.summary.match('([^ ]*[ ]{0,1}){1,6}')[0];
  47. // end underscores (italic)
  48. this.summary = this.summary.trim().replace(/_([^_]+)$/g, "_$1_");
  49. // end brackets (links)
  50. this.summary = this.summary.replace(/\[([^\]]+)$/g, "$1");
  51. // render the marckdown
  52. this.summary = markdown.renderInline(this.summary) + " …";
  53. }
  54. },
  55. oninit(vn){
  56. // console.log('Dot init : vn',vn);
  57. this.id = vn.attrs.id;
  58. this.type = vn.attrs.type;
  59. this.dottype = vn.attrs.dottype;
  60. this.setupTitle(vn);
  61. this.setuptext(vn);
  62. // console.log(`${this.id} -> ${this.dottype}`);
  63. if(typeof vn.attrs.active !== 'undefined')
  64. this.active = vn.attrs.active;
  65. // links
  66. this.links = _dbs.data_strct[this.id];
  67. // console.log(this.links);
  68. // parents memorize where do we come from to avoid duplicates and looping nav
  69. if(vn.attrs.parents){
  70. this.parents = this.parents.concat(vn.attrs.parents);
  71. // console.log('_Dot init '+this.id+' parents :',this.parents);
  72. }
  73. },
  74. oncreate(vn){
  75. if(this.active){
  76. vn.dom.classList.remove('disabled');
  77. }else{
  78. vn.dom.classList.add('disabled');
  79. }
  80. },
  81. onbeforeupdate(vn){
  82. // console.log('onbeforeupdate');
  83. if(this.lang != _dbs.lang){
  84. this.lang = _dbs.lang;
  85. this.setuptext(vn);
  86. this.setupTitle(vn);
  87. }
  88. },
  89. setOpenedContent(vn){
  90. this.dot_content = [
  91. // links to
  92. this.links.to.length
  93. ? m('nav', {'class':'links to'}, this.links.to.map(id => {
  94. // console.log(id);
  95. if(typeof _dbs.data_byid[_dbs.lang][id] !== 'undefined'){
  96. var obj = _dbs.data_byid[_dbs.lang][id];
  97. // console.log('link to : obj', obj);
  98. return m(_Dot, {
  99. "id":id,
  100. 'text':obj.text,
  101. 'dottype':obj.dottype,
  102. 'type':obj.type,
  103. // passe the memory of crossed dots plus the current one
  104. 'parents':vn.state.parents.concat([vn.state.id]),
  105. // activate link only if not in parents (already went through it)
  106. 'active':vn.state.parents.indexOf(id) == -1 ? true:false
  107. });
  108. }
  109. })
  110. )
  111. : null, // if no links to, add nothing
  112. // id
  113. // m('span', {'class':'id'}, this.id), // this.type+' '+
  114. // bullet
  115. // m('span', {'class':'bullet'}, m.trust('⚫')),
  116. // Title
  117. m('span', {'class':'title'}, m.trust(this.title)),
  118. // full text
  119. m('section', {
  120. 'class':'text',
  121. onmouseover(e){
  122. e.preventDefault();
  123. if(e.target.nodeName == "A" ){
  124. // console.log("over e.target", e.target);
  125. // console.log('over vn', vn);
  126. var id = e.target.getAttribute("href");
  127. // add highlight class
  128. vn.dom.querySelector('nav.links>div[uid="'+id+'"]').classList.add('highlight');
  129. }else{
  130. // remove all hilight class
  131. for (link of vn.dom.querySelectorAll('nav.links>div.dot')) {
  132. link.classList.remove('highlight');
  133. }
  134. }
  135. },
  136. onclick(e){
  137. e.preventDefault();
  138. if(e.target.nodeName == "A" ){
  139. // console.log("over e.target", e.target);
  140. // console.log('over vn', vn);
  141. var id = e.target.getAttribute("href");
  142. // add highlight class
  143. vn.dom.querySelector('nav.links>div[uid="'+id+'"]>.summary').click();
  144. }
  145. }
  146. }, m.trust(this.rendered_text)),
  147. // links from
  148. this.links.from.length
  149. ? m('nav', {'class':'links from'}, this.links.from.map(id => {
  150. var obj = _dbs.data_byid[_dbs.lang][id];
  151. // console.log('link from : obj', obj);
  152. // return a dot
  153. return m(_Dot, {
  154. "id":id,
  155. 'text':obj.text,
  156. 'dottype':obj.dottype,
  157. 'type':obj.type,
  158. // passe the memory of crossed dots plus the current one
  159. 'parents':vn.state.parents.concat([vn.state.id]),
  160. // activate link only if not in parents (already went through it)
  161. 'active':vn.state.parents.indexOf(id) == -1 ? true:false
  162. });
  163. })
  164. )
  165. : null, // if no links from, add nothing
  166. ];
  167. },
  168. setPreviewContent(vn){
  169. this.dot_content = [
  170. // m('span', {'class':'id'}, this.id), // this.type+' '+
  171. // m('span', {'class':'bullet'}, m.trust('•')),
  172. m('span', {
  173. 'class':'title',
  174. onclick(e){
  175. // TODO: animate openening (text and links separatly)
  176. vn.state.opened = true;
  177. }
  178. }, m.trust(this.title)), // TODO: on nested dot add full description : Part 1, Prop 8, scolie
  179. m('p', {
  180. 'class':'summary',
  181. onclick(e){
  182. // TODO: animate openening (text and links separatly)
  183. vn.state.opened = true;
  184. }
  185. }, m.trust(this.summary))
  186. ];
  187. },
  188. view(vn){
  189. if (this.active && this.opened) {
  190. // full view of dot with linked dots
  191. this.setOpenedContent(vn);
  192. }else{
  193. // preview dot
  194. this.setPreviewContent(vn);
  195. }
  196. return m('div',{
  197. 'uid':this.id,
  198. 'class':`dot ${this.dottype}`,
  199. },
  200. this.dot_content
  201. );
  202. },
  203. onupdate(vn){
  204. // console.log('_Dot : onupdate', vn);
  205. if(this.active){
  206. if (this.opened){
  207. vn.dom.classList.add('opened');
  208. if(this.links.to.length)
  209. vn.dom.classList.add('to-links');
  210. if(this.links.from.length)
  211. vn.dom.classList.add('from-links');
  212. }else{
  213. vn.dom.classList.remove('opened');
  214. }
  215. }
  216. }
  217. }
  218. /*
  219. down vote
  220. Here's full list of black dotlikes from unicode
  221. ● - ● - Black Circle
  222. ⏺ - ⏺ - Black Circle for Record
  223. ⚫ - ⚫ - Medium Black Circle
  224. ⬤ - ⬤ - Black Large Circle
  225. ⧭ - ⧭ - Black Circle with Down Arrow
  226. 🞄 - 🞄 - Black Slightly Small Circle
  227. • - • - Bullet
  228. ∙ - ∙ - Bullet Operator
  229. ⋅ - ⋅ - Dot Operator
  230. 🌑 - 🌑 - New Moon Symbol
  231. */
  232. // _______ _ __ __
  233. // / ___/ / (_) /__/ /
  234. // / /__/ _ \/ / / _ /
  235. // \___/_//_/_/_/\_,_/
  236. var _Child = {
  237. id:null,
  238. part:null,
  239. type:null,
  240. dottype:null,
  241. // nested:false,
  242. text:'',
  243. oninit(vn){
  244. // console.log('vn.attrs', vn.attrs);
  245. this.id = vn.attrs.id;
  246. this.type = vn.attrs.type;
  247. // vn.state.part = vn.state.slug.match(/^(\d)(.+)/)[1];
  248. this.text = vn.attrs.text;
  249. // this.nested = vn.attrs.nested || false;
  250. this.dottype = vn.attrs.dottype;
  251. },
  252. onbeforeupdate(vn, old){
  253. // this.nested = vn.attrs.nested || false;
  254. this.type = vn.attrs.type;
  255. this.text = vn.attrs.text;
  256. },
  257. view(vn){
  258. return m(_Dot, {"id":this.id, 'text':this.text, 'type':this.type, 'dottype':this.dottype});
  259. }
  260. };
  261. // ______
  262. // / ____/___ ____ ____ ________
  263. // / __/ / __ \/ __ \/ __ \/ ___/ _ \
  264. // / /___/ / / / /_/ / / / / /__/ __/
  265. // /_____/_/ /_/\____/_/ /_/\___/\___/
  266. var _Enonce = {
  267. partid:null,
  268. id:null,
  269. title:null,
  270. text:null,
  271. dottype:null,
  272. // nested:false,
  273. childs:[],
  274. oninit(vn){
  275. // // console.log('Enonce on init', vn);
  276. this.partid = vn.attrs.partid;
  277. this.id = vn.attrs.id;
  278. this.title = vn.attrs.title || "";
  279. this.text = vn.attrs.text;
  280. this.childs = vn.attrs.childs || [];
  281. // this.nested = vn.attrs.nested || false;
  282. this.dottype = vn.attrs.dottype;
  283. },
  284. onbeforeupdate(vn, old) {
  285. // console.log(vn.attrs.childs);
  286. this.title = vn.attrs.title || "";
  287. this.text = vn.attrs.text;
  288. this.childs = vn.attrs.childs || [];
  289. // this.nested = vn.attrs.nested || false;
  290. // if(vn.attrs.id == '1d1') console.log('_Enonce UPDATE, text :', vn.attrs.text);
  291. this.dottype = vn.attrs.dottype;
  292. },
  293. view(vn){
  294. // if(vn.attrs.id == '1d1') console.log('_Enonce VIEW, text :', vn.attrs.text);
  295. return [
  296. // create dot
  297. m(_Dot, {"id":this.id, 'text':this.text, 'type':this.title, 'dottype':this.dottype}),
  298. // addd children
  299. this.childs.map(c => { return m(_Child, c); })
  300. ]
  301. }
  302. }
  303. // ____ __
  304. // / __ \____ ______/ /_
  305. // / /_/ / __ `/ ___/ __/
  306. // / ____/ /_/ / / / /_
  307. // /_/ \__,_/_/ \__/
  308. var _Part = {
  309. oninit(vn){
  310. this.id = vn.attrs.id;
  311. this.title = vn.attrs.title || "";
  312. this.enonces = vn.attrs.enonces;
  313. },
  314. onbeforeupdate(vn, old){
  315. // console.log('_Part, onbeforeupdate old',old);
  316. this.title = vn.attrs.title || "";
  317. this.enonces = vn.attrs.enonces;
  318. },
  319. view(vn){
  320. // console.log(vn.attrs.enonces);
  321. return m("section", {
  322. 'id' :this.id,
  323. 'class' :'part'
  324. },
  325. [
  326. // create title node
  327. m("h1", {'class':'part-title', 'part':this.id}, m.trust(markdown.renderInline(this.title))),
  328. // create text node
  329. this.enonces.map(e => {
  330. // console.log(e.text);
  331. // return m(_Enonce, Object.assign({"partid":this.id},e))
  332. switch (e.type) {
  333. case "title":
  334. // handle titles
  335. return m("h2", {'class':'title'}, m.trust(markdown.renderInline(e.title)));
  336. break;
  337. case "filet":
  338. // handle filets
  339. return m("h4", {'class':'filet'}, m.trust(markdown.renderInline(e.title)));
  340. break;
  341. default:
  342. // or build structure
  343. return m(_Enonce, Object.assign({"partid":this.id},e));
  344. }
  345. })
  346. ]
  347. )
  348. }
  349. }
  350. // ____ __
  351. // / _/___ / /__________
  352. // / // __ \/ __/ ___/ __ \
  353. // _/ // / / / /_/ / / /_/ /
  354. // /___/_/ /_/\__/_/ \____/
  355. var _Intro = {
  356. oninit(vn){
  357. console.log('_Intro : oninit : vn', vn);
  358. this.id = vn.attrs.id;
  359. this.text = vn.attrs.text || '';
  360. },
  361. onbeforeupdate(vn, old){
  362. this.id = vn.attrs.id;
  363. this.text = vn.attrs.text || '';
  364. },
  365. view(vn){
  366. return m("section", {'class':'intro'}, m("p",m.trust(markdown.renderInline(this.text))));
  367. }
  368. }
  369. // ______ __ _
  370. // / ____/___ ____ ____ ___ _____/ /_(_)___ ____ _____
  371. // / / / __ \/ __ \/ __ \/ _ \/ ___/ __/ / __ \/ __ \/ ___/
  372. // / /___/ /_/ / / / / / / / __/ /__/ /_/ / /_/ / / / (__ )
  373. // \____/\____/_/ /_/_/ /_/\___/\___/\__/_/\____/_/ /_/____/
  374. module.exports = {
  375. oncreate(vn){
  376. document.body.classList.add('mode-connections');
  377. _Ui.init();
  378. },
  379. view(vn){
  380. // console.log('_ModeConnections view', vn.attrs.lang);
  381. return m('main', {id:"content", 'class':'mode-connections'}, _dbs.data[vn.attrs.lang].map(p => {
  382. if(p.id == 'intro'){
  383. return m(_Intro,p);
  384. }else{
  385. return m(_Part,p);
  386. }
  387. })
  388. );
  389. }
  390. }