main.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /**
  2. * @Author: Bachir Soussi Chiadmi <bach>
  3. * @Date: 16-04-2017
  4. * @Email: bachir@figureslibres.io
  5. * @Last modified by: bach
  6. * @Last modified time: 18-04-2017
  7. * @License: GPL-V3
  8. */
  9. require('normalize.css/normalize.css');
  10. require('./fonts/amiri/amiri.css');
  11. require('./fonts/dejavu/dejavu.css');
  12. require('./fonts/opensans/opensans.css');
  13. var m = require('mithril');
  14. // var marked = require('marked');
  15. var markdown = require('markdown-it')()
  16. .use(require('markdown-it-footnote'));
  17. var _lang;
  18. var _langs = [
  19. {'lc':'fr', 'label':'fr (appuhn)', 'db':'2-Appuhn-FR-ethicadb.json'},
  20. {'lc':'bra', 'label':'bra', 'db':'ethica-bresilen.json'}
  21. ];
  22. // console.log(_langs);
  23. var _dbs = {};
  24. var _dbs_by_id = {};
  25. var _loaded_dbs = 0;
  26. function init(){
  27. // var hash = window.location.hash;
  28. _lang = getUrlVars()['lang'] || 'fr';
  29. console.log(_lang);
  30. // create lang menu
  31. m.mount(document.getElementById('menus'), _LangMenu);
  32. // load all dbs, when loaded init main app
  33. for (var i = 0; i < _langs.length; i++) {
  34. // if(_langs[i].lc == lang){
  35. // var dbfile = _langs[i].db;
  36. // }
  37. loadJSON(_langs[i].lc, 'assets/jsondb/'+_langs[i].db, onDBLoaded);
  38. }
  39. };
  40. // __ __ ___
  41. // / / ____ _____ ____ _/ |/ /__ ____ __ __
  42. // / / / __ `/ __ \/ __ `/ /|_/ / _ \/ __ \/ / / /
  43. // / /___/ /_/ / / / / /_/ / / / / __/ / / / /_/ /
  44. // /_____/\__,_/_/ /_/\__, /_/ /_/\___/_/ /_/\__,_/
  45. // /____/
  46. var _LangMenu = {
  47. view: function(){
  48. // return m('main', {id:"content"}, DataItems.map(c => m(_Item,c)));
  49. // create ul dom
  50. return m('ul', {id:"languages"}, _langs.map(function(lang){
  51. // create li dom for each lank link
  52. return m('li',
  53. // create a dom
  54. m('a', {
  55. 'lang':lang.lc,
  56. 'href':'/?lang='+lang.lc,
  57. onclick:function(e){
  58. e.preventDefault();
  59. // console.log('click lang', e);
  60. var lang = e.target.getAttribute('lang');
  61. console.log(lang);
  62. if(lang != _lang){
  63. // change url variable
  64. // change db
  65. _lang = lang;
  66. // redraw UI
  67. m.redraw();
  68. }
  69. return false;
  70. }
  71. }, lang.label)
  72. );
  73. })
  74. );
  75. }
  76. }
  77. // _
  78. // (_)________ ____
  79. // / / ___/ __ \/ __ \
  80. // / (__ ) /_/ / / / /
  81. // __/ /____/\____/_/ /_/
  82. // /___/
  83. function loadJSON(lc, file, callback) {
  84. var xobj = new XMLHttpRequest();
  85. xobj.overrideMimeType("application/json");
  86. // xobj.setRequestHeader('Accept-Encoding', 'gzip');
  87. xobj.open('GET', file, true); // Replace 'my_data' with the path to your file
  88. // xobj.onload = callback;
  89. xobj.onreadystatechange = function () {
  90. // console.log(xobj);
  91. if (xobj.readyState == 4 && xobj.status == "200") {
  92. // Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
  93. callback(lc, xobj.responseText);
  94. }
  95. };
  96. xobj.send(null);
  97. // TODO: load and unzip gziped json
  98. // TODO: load multiple languages jsons
  99. };
  100. function onDBLoaded(lc, json){
  101. _dbs[lc] = JSON.parse(json);
  102. _loaded_dbs ++;
  103. if (_loaded_dbs == _langs.length) {
  104. console.log("_dbs", _dbs);
  105. parseDBs();
  106. m.mount(document.getElementById('app'), _Tree);
  107. }
  108. }
  109. function parseDBs(){
  110. for(l in _dbs){
  111. // console.log('l', l);
  112. _dbs_by_id[l] = {};
  113. for (p in _dbs[l]) {
  114. // console.log(_dbs[l][p]);
  115. for (e in _dbs[l][p].enonces) {
  116. // console.log('e',e);
  117. _dbs_by_id[l][_dbs[l][p].enonces[e].id] = _dbs[l][p].enonces[e];
  118. for (c in _dbs[l][p][e]){
  119. // console.log(_db[p][e][c]);
  120. _dbs_by_id[_dbs[l][p][e][c].id] = _dbs[l][p][e][c];
  121. }
  122. }
  123. }
  124. }
  125. console.log('_dbs_by_id', _dbs_by_id);
  126. }
  127. // __ _ __
  128. // / / (_)___ / /__
  129. // / / / / __ \/ //_/
  130. // / /___/ / / / / ,<
  131. // /_____/_/_/ /_/_/|_|
  132. var _Link = {
  133. targetid:"",
  134. opened:false,
  135. oninit: function(vn){
  136. // console.log("INIT LINK : vn", vn);
  137. // define target id
  138. vn.state.tid = vn.attrs.href;
  139. },
  140. onupdate: function(vn){
  141. vn.state.tid = vn.attrs.href;
  142. },
  143. view: function(vn){
  144. if(vn.state.opened){
  145. // console.log('vn.state.tid', vn.state);
  146. return m('div', {'class':'opened-link'},
  147. [
  148. m('span', {'class':"link text"}, vn.children),
  149. typeof _dbs_by_id[_lang][vn.state.tid].childs != "undefined"
  150. ? m(_Enonce, _dbs_by_id[_lang][vn.state.tid])
  151. : m(_Item, _dbs_by_id[_lang][vn.state.tid])
  152. ]
  153. );
  154. }else{
  155. // console.log(vn);
  156. return m('a', {
  157. 'class':'link',
  158. 'href':'#'+vn.state.tid,
  159. 'rel':vn.state.tid,
  160. onclick:function(e){
  161. e.preventDefault();
  162. console.log('click', vn);
  163. vn.state.opened = true;
  164. return false;
  165. }
  166. }, vn.children);
  167. }
  168. }
  169. }
  170. // ______ __
  171. // /_ __/__ _ __/ /_
  172. // / / / _ \| |/_/ __/
  173. // / / / __/> </ /_
  174. // /_/ \___/_/|_|\__/
  175. // recusive function to record information of all subnodes
  176. function parseTextDom(nodes){
  177. var list = [];
  178. // loop through childNodes
  179. for (var i = 0; i < nodes.length; i++) {
  180. var n = {};
  181. if(typeof nodes[i].localName != "undefined"){
  182. n.tag=nodes[i].localName;
  183. if (n.tag == 'p') {
  184. // replace p by div as we will insert other div in them
  185. n.tag = 'div';
  186. n.attrs = {'class':'paragraph'};
  187. }
  188. if (n.tag == 'a') {
  189. // record the href attribute for cross reference
  190. n.attrs = {'href':nodes[i].attributes.href.value};
  191. }
  192. if(nodes[i].childNodes.length){
  193. // again parse node's childs
  194. n.childs = parseTextDom(nodes[i].childNodes);
  195. }
  196. }else if (nodes[i].textContent.length > 1){
  197. // if node has no localName it is probably a #text node
  198. // we record it if it's not empty
  199. n.tag='#text';
  200. n.text=nodes[i].textContent;
  201. }
  202. // add the node to the list if it has a tag
  203. if(typeof n.tag != "undefined")
  204. list.push(n);
  205. }
  206. return list;
  207. }
  208. // recusive fucntion to generate mithril object from information recorded with parseTextDom()
  209. function populateTextDom(n,i){
  210. // console.log('populateTextDom : '+i,n);
  211. return n.tag == "#text"
  212. ? m.trust(n.text)
  213. : m(
  214. n.tag != 'a' ? n.tag : _Link,
  215. typeof n.attrs != "undefined" ? n.attrs : {},
  216. typeof n.childs != "undefined"
  217. ? n.childs.map(populateTextDom)
  218. : typeof n.text != "undefined"
  219. ? m.trust(n.text)
  220. : null
  221. );
  222. }
  223. var _Text = {
  224. textchilds:[],
  225. oninit: function(vn){
  226. // debug = vn.attrs.id == '1a5';
  227. // convert markdown to html
  228. var texthtml = markdown.render(vn.attrs.text)
  229. // TODO: fixe number link text disapear [3](1d3) ( in 104d )
  230. // TODO: fixe parenthèse disparait _(par les Défin. [test 3](1d3) et [test 5](1d5))_ ( in 104d )
  231. // parse html string to virtual dom
  232. var textdom = new DOMParser().parseFromString(texthtml, "text/html");
  233. // get the text nodes (avoid html document extra)
  234. // if(debug) console.log('textdom',textdom);
  235. vn.state.textchilds = parseTextDom(textdom.getElementsByTagName('body')[0].childNodes);
  236. },
  237. onupdate: function(vn){
  238. var texthtml = markdown.render(vn.attrs.text)
  239. var textdom = new DOMParser().parseFromString(texthtml, "text/html");
  240. vn.state.textchilds = parseTextDom(textdom.getElementsByTagName('body')[0].childNodes);
  241. },
  242. view: function(vn){
  243. // console.log('_Text :: view : '+vn.attrs.slug, vn);
  244. // console.log('vn.state.textchilds', vn.state.textchilds);
  245. return m('div',
  246. {'class':'text'},
  247. // loop through childNodes list generated by parseTextDom() in init
  248. vn.state.textchilds.map(populateTextDom)
  249. ); // /m.div.text
  250. } // view:
  251. }
  252. // ______
  253. // / _/ /____ ____ ___
  254. // / // __/ _ \/ __ `__ \
  255. // _/ // /_/ __/ / / / / /
  256. // /___/\__/\___/_/ /_/ /_/
  257. var _Item = {
  258. // id:null,
  259. // part:null,
  260. // type:null,
  261. // nested:false,
  262. // oninit: function(vn){
  263. // // console.log('vn.attrs', vn.attrs);
  264. // vn.state.id = vn.attrs.id;
  265. // // vn.state.part = vn.state.slug.match(/^(\d)(.+)/)[1];
  266. // vn.state.nested = vn.attrs.nested | false;
  267. // },
  268. view: function(vn){
  269. return m("section", {
  270. 'id':vn.attrs.id,
  271. 'class':'item'+((vn.attrs.nested || false) ? ' nested':'')
  272. },
  273. [
  274. // create title node
  275. m("h3", {
  276. // 'ref':vn.attrs.href,
  277. onclick: function(e){
  278. vn.state.active = vn.state.active ? 0 : 1;
  279. }
  280. }, vn.attrs.type),
  281. // create text node
  282. m(_Text, {'text':vn.attrs.text, 'id':vn.attrs.id})
  283. ]
  284. )
  285. }
  286. };
  287. // ______
  288. // / ____/___ ____ ____ ________
  289. // / __/ / __ \/ __ \/ __ \/ ___/ _ \
  290. // / /___/ / / / /_/ / / / / /__/ __/
  291. // /_____/_/ /_/\____/_/ /_/\___/\___/
  292. var _Enonce = {
  293. // partid:null,
  294. // id:null,
  295. // title:null,
  296. // nested:false,
  297. childs:[],
  298. oninit:function(vn){
  299. // // console.log('Enonce on init', vn);
  300. // vn.state.partid = vn.attrs.partid;
  301. // vn.state.id = vn.attrs.id;
  302. // vn.state.title = vn.attrs.title;
  303. vn.state.childs = vn.attrs.childs;
  304. // vn.state.nested = vn.attrs.nested | false;
  305. },
  306. onupdate:function(vn) {
  307. vn.state.childs = vn.attrs.childs;
  308. },
  309. view: function(vn){
  310. return m("section", {
  311. 'id' :vn.attrs.id,
  312. 'class' :'enonce'+((vn.attrs.nested || false) ? ' nested':'')
  313. },
  314. [
  315. // create title node
  316. m("h2", {}, vn.attrs.title),
  317. // create text node
  318. m(_Text, {'text':vn.attrs.text, 'id':vn.attrs.id}),
  319. // addd children
  320. vn.state.childs.map(function(c){
  321. return m(_Item, c)
  322. })
  323. ])
  324. }
  325. }
  326. // ____ __
  327. // / __ \____ ______/ /_
  328. // / /_/ / __ `/ ___/ __/
  329. // / ____/ /_/ / / / /_
  330. // /_/ \__,_/_/ \__/
  331. var _Part = {
  332. view: function(vn){
  333. return m("section", {
  334. 'id' :vn.attrs.id,
  335. 'class' :'part'
  336. },
  337. [
  338. // create title node
  339. m("h1", {'class':'part'}, vn.attrs.title),
  340. // create text node
  341. vn.attrs.enonces.map(function(e){
  342. return m(_Enonce, Object.assign({"partid":vn.attrs.id},e))
  343. })
  344. ])
  345. }
  346. }
  347. // ______
  348. // /_ __/_______ ___
  349. // / / / ___/ _ \/ _ \
  350. // / / / / / __/ __/
  351. // /_/ /_/ \___/\___/
  352. var _Tree = {
  353. view: function(){
  354. console.log('_Tree view', _lang);
  355. return m('main', {id:"content"}, _dbs[_lang].map(function(p){
  356. // console.log("MAP _dbs", p);
  357. return m(_Part,p);
  358. })
  359. );
  360. }
  361. }
  362. // __ __ __
  363. // / / / /__ / /___ ___ __________
  364. // / /_/ / _ \/ / __ \/ _ \/ ___/ ___/
  365. // / __ / __/ / /_/ / __/ / (__ )
  366. // /_/ /_/\___/_/ .___/\___/_/ /____/
  367. // /_/
  368. function getUrlVars() {
  369. var vars = {};
  370. var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
  371. vars[key] = value;
  372. });
  373. return vars;
  374. }
  375. // _ _ __
  376. // (_)___ (_) /_
  377. // / / __ \/ / __/
  378. // / / / / / / /_
  379. // /_/_/ /_/_/\__/
  380. init()