ModeConnections.js 12 KB

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