ModeConnections.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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. oninit(vn){
  237. // // console.log('vn.attrs', vn.attrs);
  238. // this.id = vn.attrs.id;
  239. // this.type = vn.attrs.type;
  240. // // vn.state.part = vn.state.slug.match(/^(\d)(.+)/)[1];
  241. // this.text = vn.attrs.text;
  242. // // this.nested = vn.attrs.nested || false;
  243. // this.dottype = vn.attrs.dottype;
  244. },
  245. onbeforeupdate(vn, old){
  246. // // this.nested = vn.attrs.nested || false;
  247. // this.type = vn.attrs.type;
  248. // this.text = vn.attrs.text;
  249. },
  250. view(vn){
  251. // return m(_Dot, {"id":this.id, 'text':this.text, 'type':this.type, 'dottype':this.dottype});
  252. return m(_Dot, vn.attrs);
  253. }
  254. };
  255. // ______
  256. // / ____/___ ____ ____ ________
  257. // / __/ / __ \/ __ \/ __ \/ ___/ _ \
  258. // / /___/ / / / /_/ / / / / /__/ __/
  259. // /_____/_/ /_/\____/_/ /_/\___/\___/
  260. var _Enonce = {
  261. partid:null,
  262. id:null,
  263. title:null,
  264. text:null,
  265. dottype:null,
  266. // nested:false,
  267. childs:[],
  268. oninit(vn){
  269. // // // console.log('Enonce on init', vn);
  270. // this.partid = vn.attrs.partid;
  271. // this.id = vn.attrs.id;
  272. // this.title = vn.attrs.title || "";
  273. // this.text = vn.attrs.text;
  274. // this.childs = vn.attrs.childs || [];
  275. // // this.nested = vn.attrs.nested || false;
  276. // this.dottype = vn.attrs.dottype;
  277. },
  278. onbeforeupdate(vn, old) {
  279. // // console.log(vn.attrs.childs);
  280. // this.title = vn.attrs.title || "";
  281. // this.text = vn.attrs.text;
  282. // this.childs = vn.attrs.childs || [];
  283. // // this.nested = vn.attrs.nested || false;
  284. // // if(vn.attrs.id == '1d1') console.log('_Enonce UPDATE, text :', vn.attrs.text);
  285. // this.dottype = vn.attrs.dottype;
  286. },
  287. view(vn){
  288. // if(vn.attrs.id == '1d1') console.log('_Enonce VIEW, text :', vn.attrs.text);
  289. return [
  290. // create dot
  291. // m(_Dot, {
  292. // 'id':this.id
  293. // 'text':this.text
  294. // 'type':this.title
  295. // 'dottype':this.dottype
  296. // }),
  297. m(_Dot, vn.attrs),
  298. // addd children
  299. vn.attrs.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. }