corpus.js 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317
  1. /**
  2. * @Author: Bachir Soussi Chiadmi <bach>
  3. * @Date: 18-12-2017
  4. * @Email: bachir@figureslibres.io
  5. * @Filename: corpus.js
  6. * @Last modified by: bach
  7. * @Last modified time: 20-12-2017
  8. * @License: GPL-V3
  9. */
  10. // JS performance improvement http://archive.oreilly.com/pub/a/server-administration/excerpts/even-faster-websites/writing-efficient-javascript.html
  11. /**
  12. * depends on :
  13. * physics.js : http://jonobr1.com/Physics/#
  14. */
  15. (function($, Drupal, drupalSettings) {
  16. EdlpCorpus = function(){
  17. var _activated = true;
  18. var _$body = $('body');
  19. var _$container = _$body;
  20. var _$canvas = $('<canvas id="corpus-map">').appendTo(_$container);
  21. var _canvas = _$canvas[0];
  22. var _ctx = _canvas.getContext('2d');
  23. var _dpi = window.devicePixelRatio;
  24. var _is_expo = $('body').hasClass('domain-expo-encyclopediedelaparole-org');
  25. var _scene_props = {
  26. width:window.innerWidth,
  27. height:window.innerHeight,
  28. // 'margin_top':90, // with red border on head
  29. 'margin_top': _is_expo ? 0 : 75, // without red border on head
  30. // 'margin_top':0,
  31. 'margin_right':0,
  32. 'margin_bottom': _is_expo ? 0 : 65,
  33. // 'margin_bottom':0,
  34. 'margin_left':0
  35. };
  36. var _evolution_zone = {
  37. left:_scene_props.width/4,
  38. right:_scene_props.width - _scene_props.width/4,
  39. center:_scene_props.width/2,
  40. };
  41. var _physics = new Physics();
  42. var _nodes = [];
  43. var _articles_nodes = [];
  44. var _no_articles_nodes = [];
  45. // var _articles_filter_on = false;
  46. var _nodes_by_entries = {};
  47. var _nodes_by_nid = {};
  48. var _nodes_Nid_Id = {};
  49. var _nodes_centered = [];
  50. var _nodes_centered_attractions = [];
  51. var _loaded = false;
  52. var _playlist = [];
  53. var _p_velocity_factor = 0.5;
  54. var _mouse_in = true;
  55. var _m_pos = {x:0, y:0};
  56. var _node_hover_id = -1;
  57. var _node_opened_id = -1;
  58. var _$entrees_block = $('#block-edlpentreesblock');
  59. var _$entrees_block_termlinks = $('a.term-link', _$entrees_block);
  60. var _$articles_link;
  61. var _node_pop_up;
  62. // Colors depend on drupalSettings loaded by edlp_corpus.module
  63. var _settings = drupalSettings.edlp_corpus;
  64. var _ecolors = _settings.colors;
  65. // Physics
  66. var _attracter;
  67. var check_parts_colid_frq = 2;
  68. var check_parts_colid_tick = 1;
  69. // ____ _ __
  70. // / _/___ (_) /______
  71. // / // __ \/ / __/ ___/
  72. // _/ // / / / / /_(__ )
  73. // /___/_/ /_/_/\__/____/
  74. function init(){
  75. console.log("Corpus init()");
  76. initCanvas();
  77. if(_activated){
  78. loadCorpus();
  79. }else{
  80. _$canvas.addClass('de-activated');
  81. }
  82. };
  83. // ___
  84. // / __|__ _ _ ___ ____ _ ___
  85. // | (__/ _` | ' \ V / _` (_-<
  86. // \___\__,_|_||_\_/\__,_/__/
  87. function initCanvas(){
  88. // resize the canvas to fill browser window dynamically
  89. window.addEventListener('resize', onResizeCanvas, false);
  90. onResizeCanvas();
  91. };
  92. function onResizeCanvas() {
  93. // _dpi = 2;
  94. _scene_props.width = window.innerWidth;
  95. _scene_props.height = window.innerHeight;
  96. _canvas.style.width = _scene_props.width+'px';
  97. _canvas.style.height = _scene_props.height+'px';
  98. _canvas.width = _scene_props.width*_dpi;
  99. _canvas.height = _scene_props.height*_dpi;
  100. _ctx.scale(_dpi, _dpi);
  101. moveEvolutionZone();
  102. if(_loaded){
  103. for (var i = 0; i < _nodes.length; i++) {
  104. _nodes[i].onResizeCanvas();
  105. }
  106. // move _attracter and _repulser to their right places again
  107. // moveEvolutionZone() will trigger resizePhysics()
  108. // resizePhysics();
  109. }
  110. };
  111. // ___
  112. // / __|___ _ _ _ __ _ _ ___
  113. // | (__/ _ \ '_| '_ \ || (_-<
  114. // \___\___/_| | .__/\_,_/__/
  115. // |_|
  116. function loadCorpus(){
  117. // console.log('drupalSettings',drupalSettings);
  118. // console.log('window.location', window.location);
  119. // var path = window.location.origin + drupalSettings.basepath + "edlp/corpus";
  120. var ajax_path = _settings.load_corpus_ajax_url;
  121. var path = window.location.origin + Drupal.url(ajax_path);
  122. $.getJSON(path, {})
  123. .done(function(data){
  124. onCorpusLoaded(data);
  125. })
  126. .fail(function(jqxhr, textStatus, error){
  127. onCorpusLoadError(jqxhr, textStatus, error);
  128. });
  129. };
  130. function onCorpusLoadError(jqxhr, textStatus, error){
  131. console.warn('corpus load failed', jqxhr.responseText);
  132. };
  133. function onCorpusLoaded(data){
  134. console.log('corpus loaded : data', data);
  135. // console.log('first node', data.nodes[0]);
  136. // buildParticles(data.nodes);
  137. initPhysics();
  138. buildNodes(data.nodes);
  139. initArtilesLink();
  140. initNodePopup();
  141. initEvents();
  142. checkPreOpenedEntry();
  143. startAnime();
  144. _loaded = true;
  145. };
  146. // ___ _ _
  147. // | _ \ |_ _ _ __(_)__ ___
  148. // | _/ ' \ || (_-< / _(_-<
  149. // |_| |_||_\_, /__/_\__/__/
  150. // |__/
  151. function initPhysics(){
  152. _attracter = _physics.makeParticle(1000);
  153. _attracter.fixed = true;
  154. // move _attracter on window resize
  155. resizePhysics();
  156. };
  157. function resizePhysics(){
  158. // attracters
  159. if(typeof _attracter != 'undefined'){
  160. _attracter.position = {x:_evolution_zone.center, y:_scene_props.height/2};
  161. }
  162. };
  163. // _ _ _
  164. // | \| |___ __| |___ ___
  165. // | .` / _ \/ _` / -_|_-<
  166. // |_|\_\___/\__,_\___/__/
  167. function buildNodes(nodes){
  168. // console.log("buildNodes", nodes);
  169. var d;
  170. for (var i in nodes) {
  171. d = i < 1 ? true : false;
  172. // _nodes.push(new Node(i,nodes[i],d));
  173. new Node(i,nodes[i],d);
  174. _playlist.push({
  175. 'id':i,
  176. 'nid':nodes[i].nid,
  177. 'audio_url':nodes[i].audio_url,
  178. 'document_url':nodes[i].document_url,
  179. });
  180. }
  181. };
  182. function Node(i,node,d){
  183. this.id = i;
  184. for(key in node)
  185. this[key] = node[key];
  186. // record the node in different lists
  187. _nodes.push(this);
  188. _nodes_by_nid[this.nid] = this;
  189. _nodes_Nid_Id[this.nid] = this.id;
  190. if(this.has_article == 1){
  191. _articles_nodes.push(this);
  192. }else{
  193. _no_articles_nodes.push(this);
  194. }
  195. for (var j = 0; j < this.entrees.length; j++) {
  196. if(typeof _nodes_by_entries[this.entrees[j]] == 'undefined')
  197. _nodes_by_entries[this.entrees[j]] = [];
  198. _nodes_by_entries[this.entrees[j]].push(this);
  199. }
  200. this.debug = d;
  201. this.mass = Math.max(1, this.entrees.length); //1;
  202. this.velocity_threshold = 0.01;
  203. // define radius regarding entries length
  204. switch(true){
  205. case this.entrees.length > 3:
  206. this.r = 8;//10;
  207. break;
  208. case this.entrees.length > 1 && this.entrees.length <= 3:
  209. this.r = 5;//7;
  210. break;
  211. default:
  212. this.r = 3;//4;
  213. break;
  214. }
  215. this.d = this.r*2;
  216. this.e_color = 'e_col_'+this.entrees[Math.floor(Math.random(this.entrees.length))];
  217. // pre-rendering node virtual canvas
  218. this.canvas = document.createElement('canvas');
  219. this.canvas_ctx = this.canvas.getContext('2d');
  220. this.line_width = 1;
  221. this.w = this.r*2+this.line_width*2;
  222. this.w_2 = this.w/2;
  223. this.canvas.width = this.w;
  224. this.canvas.height = this.w;
  225. this.canvas_ctx.fillStyle = 'rgb(255,255,255)';
  226. this.canvas_ctx.lineWidth = this.line_width;
  227. this.wall_bouncing_elasticity = 0.75;
  228. // node states
  229. this.hover = false;
  230. this.opened = false;
  231. this.faded = false;
  232. this.center = false;
  233. this.aside = false;
  234. this.scrambling = false;
  235. // prototypes
  236. if (typeof Node.initialized == "undefined") {
  237. Node.prototype.init = function(){
  238. this.calcWallLimits();
  239. this.x = this.wall_limits.left + Math.random()*(this.wall_limits.right - this.wall_limits.left);
  240. this.y = this.wall_limits.top + Math.random()*(this.wall_limits.bottom - this.wall_limits.top);
  241. this.ori_pos = {x:this.x,y:this.y};
  242. // TODO: don't forget to move ori_pos on window resize
  243. //this.drawSprite();
  244. this.initPhysics();
  245. };
  246. // Node.prototype.drawSprite = function(){
  247. // _ctx.clearRect(0, 0, this.w, this.w);
  248. //
  249. // this.canvas_ctx.beginPath();
  250. // // white background
  251. // this.canvas_ctx.fillRect(0,0,this.w,this.w);
  252. //
  253. // this.canvas_ctx.globalAlpha = this.faded ? 0.15 : 1;
  254. //
  255. // if(this.opened){
  256. // // carre plein
  257. // // this.canvas_ctx.lineWidth = '1px';
  258. // // this.canvas_ctx.strokeStyle = 'rgb(255,0,0)';
  259. // // this.canvas_ctx.strokeRect(this.x - this.r-3,this.y - this.r-3,this.r*2+6,this.r*2+6);
  260. // // ou carre contour
  261. // this.canvas_ctx.save(); // save the normal context state (fill white)
  262. // this.canvas_ctx.fillStyle = _ecolors[this.e_color];
  263. // this.canvas_ctx.fillRect(this.line_width,this.line_width,this.d,this.d);
  264. // this.canvas_ctx.restore(); // restore the normal context state (fill white)
  265. // }
  266. // // else{
  267. // // // carre plein
  268. // // // this.canvas_ctx.fillStyle = _ecolors[this.e_color];
  269. // // // this.canvas_ctx.fillRect(this.x - this.r,this.y - this.r,this.d,this.d);
  270. // // // ou carre contour
  271. // // this.canvas_ctx.fillRect(this.line_width,this.line_width,this.d,this.d);
  272. // // }
  273. // this.canvas_ctx.strokeStyle = _ecolors[this.e_color];
  274. // this.canvas_ctx.strokeRect(this.line_width,this.line_width,this.d,this.d);
  275. // // this.canvas_ctx.globalAlpha = 1;
  276. // this.canvas_ctx.closePath();
  277. // };
  278. Node.prototype.initPhysics = function(){
  279. // particule
  280. this.p = _physics.makeParticle(this.mass, this.x, this.y);
  281. this.p.velocity = new Physics.Vector((Math.random()-0.5)*_p_velocity_factor, (Math.random()-0.5)*_p_velocity_factor);
  282. // origin position particule
  283. this.ori_p = _physics.makeParticle(1000, this.ori_pos.x, this.ori_pos.y);
  284. this.ori_p.fixed = true;
  285. // TODO: don't forget to move ori_p on window resize
  286. this.ori_p_attract = _physics.makeAttraction(this.ori_p, this.p, 1000, _scene_props.width*2);
  287. this.ori_p_attract.on = false;
  288. // attracter
  289. this.attract = _physics.makeAttraction(_attracter, this.p, 1000, _scene_props.width*2);
  290. this.attract.on = false;
  291. };
  292. Node.prototype.calcWallLimits = function(){
  293. this.wall_limits = {
  294. top: _scene_props.margin_top +this.r,
  295. right: _scene_props.width -_scene_props.margin_right -this.r,
  296. bottom: _scene_props.height -_scene_props.margin_bottom -this.r,
  297. left: _scene_props.margin_left +this.r
  298. }
  299. };
  300. Node.prototype.onResizeCanvas = function(){
  301. this.calcWallLimits();
  302. // TODO: scramble only if not aside or centered
  303. this.shuffleOriP();
  304. };
  305. Node.prototype.shuffleOriP = function(){
  306. this.ori_pos.x = this.wall_limits.left + Math.random()*(this.wall_limits.right - this.wall_limits.left);
  307. this.ori_pos.y = this.wall_limits.top + Math.random()*(this.wall_limits.bottom - this.wall_limits.top);
  308. this.scramble();
  309. };
  310. Node.prototype.onUpdate = function(){
  311. // this.p.velocity.multiplyScalar(0.99);
  312. if(this.hover || this.opened){
  313. this.p.fixed = true;
  314. }else{
  315. this.p.fixed = false;
  316. if(this.center)
  317. this.limitEvolutionZone();
  318. // if(!this.p.resting()){
  319. // this.checkVelocityThreshold();
  320. this.checkWallBouncing();
  321. this.updatePos();
  322. if(this.scrambling){
  323. this.checkOriPDist();
  324. }
  325. // }
  326. }
  327. if(_mouse_in && !this.aside && !this.faded)
  328. this.checkMouse();
  329. // this.move();
  330. this.redraw();
  331. };
  332. Node.prototype.checkVelocityThreshold = function(){
  333. if(!this.centered || !this.aside){
  334. if (Math.abs(this.p.velocity.x) < this.velocity_threshold
  335. && Math.abs(this.p.velocity.y) < this.velocity_threshold){
  336. this.p.velocity.multiplyScalar(0);
  337. // this.p.makeFixed();
  338. }
  339. }
  340. };
  341. Node.prototype.checkWallBouncing = function(){
  342. switch(true){
  343. case this.x < this.wall_limits.left && this.p.velocity.x < 0:
  344. this.p.position.x = this.wall_limits.left;
  345. this.p.velocity
  346. .multiplyScalarXY(-1, 1)
  347. .multiplyScalar(this.wall_bouncing_elasticity);
  348. break;
  349. case this.x > this.wall_limits.right && this.p.velocity.x > 0:
  350. this.p.position.x = this.wall_limits.right;
  351. this.p.velocity
  352. .multiplyScalarXY(-1, 1)
  353. .multiplyScalar(this.wall_bouncing_elasticity);
  354. break;
  355. case this.y < this.wall_limits.top && this.p.velocity.y < 0 :
  356. this.p.position.y = this.wall_limits.top;
  357. this.p.velocity
  358. .multiplyScalarXY(1,-1)
  359. .multiplyScalar(this.wall_bouncing_elasticity);
  360. break;
  361. case this.y > this.wall_limits.bottom && this.p.velocity.y > 0 :
  362. this.p.position.y = this.wall_limits.bottom;
  363. this.p.velocity
  364. .multiplyScalarXY(1,-1)
  365. .multiplyScalar(this.wall_bouncing_elasticity);
  366. break;
  367. }
  368. };
  369. Node.prototype.updatePos = function(){
  370. this.x = this.p.position.x;
  371. this.y = this.p.position.y;
  372. };
  373. Node.prototype.checkMouse = function(){
  374. if( _m_pos.x > this.x - this.r
  375. && _m_pos.x < this.x + this.r
  376. && _m_pos.y > this.y - this.r
  377. && _m_pos.y < this.y + this.r){
  378. if(_node_hover_id == -1 || _node_hover_id !== this.id){
  379. // console.log("Node hover", this.id);
  380. this.setHover();
  381. }
  382. }else{
  383. this.unsetHover();
  384. }
  385. };
  386. Node.prototype.setHover = function(){
  387. this.hover = true;
  388. _node_hover_id = this.id;
  389. _node_pop_up.setNode(this);
  390. };
  391. Node.prototype.unsetHover = function(){
  392. this.hover = false;
  393. if (_node_hover_id == this.id) {
  394. _node_hover_id = -1;
  395. _node_pop_up.removeNode();
  396. }
  397. };
  398. Node.prototype.open = function(){
  399. this.opened = true;
  400. _node_opened_id = this.id;
  401. //this.drawSprite();
  402. };
  403. Node.prototype.close = function(){
  404. this.opened = false;
  405. //this.drawSprite();
  406. };
  407. Node.prototype.fade = function(){
  408. this.faded = true;
  409. //this.drawSprite();
  410. };
  411. Node.prototype.unFade = function(){
  412. this.faded = false;
  413. //this.drawSprite();
  414. };
  415. Node.prototype.setCenteredOnEntree = function(tid){
  416. this.e_color = 'e_col_'+tid;
  417. this.setCentered();
  418. };
  419. Node.prototype.setCentered = function(){
  420. this.center = true;
  421. this.stopScrambling();
  422. this.unsetAside();
  423. this.attract.on = true;
  424. //this.drawSprite();
  425. }
  426. Node.prototype.unsetCentered = function(){
  427. this.center = false;
  428. this.attract.on = false;
  429. }
  430. Node.prototype.limitEvolutionZone = function(){
  431. // smouthly slow down node near center
  432. // if(this.id == 1)
  433. // console.log('this.p.velocity', this.p.velocity);
  434. this.dist_to_attracter = this.p.distanceTo(_attracter);
  435. if( this.dist_to_attracter < _scene_props.width/4){
  436. if( this.p.velocity.length() > 0.4 ){
  437. this.p.velocity.multiplyScalar(0.99); // 0.995
  438. }
  439. }
  440. // limit evolution zone
  441. // if( Math.abs(_attracter.position.x - this.x) > _scene_props.width/4
  442. // || Math.abs(_attracter.position.y - this.y) > _scene_props.height/4){
  443. if( this.x < _evolution_zone.left || this.x > _evolution_zone.right
  444. || Math.abs(_attracter.position.y - this.y) > _scene_props.height/4){
  445. this.attract.on = true;
  446. }else{
  447. this.attract.on = false;
  448. }
  449. }
  450. Node.prototype.setAside = function(){
  451. this.aside = true;
  452. // this.fade();
  453. this.stopScrambling();
  454. this.unsetCentered();
  455. this.ori_p.position.x = this.x < _scene_props.width /2 ? this.wall_limits.left : this.wall_limits.right;
  456. this.ori_p_attract.on = true;
  457. this.wall_bouncing_elasticity = 0.15;
  458. }
  459. Node.prototype.unsetAside = function(){
  460. // console.log('unsetAside');
  461. this.aside = false;
  462. this.ori_p_attract.on = false;
  463. this.ori_p.position.x = this.ori_pos.x;
  464. this.wall_bouncing_elasticity = 0.75;
  465. // this.unFade();
  466. }
  467. Node.prototype.resolveNormalPos = function(){
  468. // console.log("resolveNormalPos");
  469. switch(true){
  470. case this.center:
  471. this.unsetCentered();
  472. break;
  473. case this.aside:
  474. this.unsetAside();
  475. break;
  476. }
  477. };
  478. Node.prototype.scramble = function(){
  479. this.scrambling = true;
  480. this.unsetCentered();
  481. this.unsetAside();
  482. this.ori_p.position.x = this.ori_pos.x;
  483. this.ori_p.position.y = this.ori_pos.y;
  484. this.ori_p_attract.on = true;
  485. }
  486. Node.prototype.checkOriPDist = function(){
  487. if(this.p.distanceTo(this.ori_p) < 50){
  488. this.stopScrambling();
  489. }
  490. };
  491. Node.prototype.stopScrambling = function(){
  492. this.scrambling = false;
  493. this.ori_p_attract.on = false;
  494. // this.scramble_TL.on = false;
  495. // this.scramble_TR.on = false;
  496. // this.scramble_BR.on = false;
  497. // this.scramble_BL.on = false;
  498. // this.scramble_CR.on = false;
  499. // this.scramble_CL.on = false;
  500. }
  501. Node.prototype.move = function(){
  502. // just draw the virtual node canvas into the main scene canvas at the right position
  503. _ctx.drawImage(this.canvas, this.x-this.w_2, this.y-this.w_2);
  504. };
  505. Node.prototype.redraw = function(){
  506. _ctx.beginPath();
  507. // white background
  508. _ctx.fillStyle = 'rgb(255,255,255)';
  509. _ctx.fillRect(this.x-this.r,this.y-this.r,this.d,this.d);
  510. _ctx.globalAlpha = this.faded ? 0.15 : 1;
  511. if(this.opened){
  512. // carre plein
  513. // _ctx.lineWidth = '1px';
  514. // _ctx.strokeStyle = 'rgb(255,0,0)';
  515. // _ctx.strokeRect(this.x - this.r-3,this.y - this.r-3,this.r*2+6,this.r*2+6);
  516. // ou carre contour
  517. // _ctx.save(); // save the normal context state (fill white)
  518. _ctx.fillStyle = _ecolors[this.e_color];
  519. _ctx.fillRect(this.x-this.r,this.y-this.r,this.d,this.d);
  520. // _ctx.restore(); // restore the normal context state (fill white)
  521. }
  522. // else{
  523. // // carre plein
  524. // // _ctx.fillStyle = _ecolors[this.e_color];
  525. // // _ctx.fillRect(this.x - this.r,this.y - this.r,this.d,this.d);
  526. // // ou carre contour
  527. // _ctx.fillRect(this.line_width,this.line_width,this.d,this.d);
  528. // }
  529. _ctx.strokeStyle = _ecolors[this.e_color];
  530. _ctx.strokeRect(this.x-this.r,this.y-this.r,this.d,this.d);
  531. // _ctx.globalAlpha = 1;
  532. _ctx.closePath();
  533. };
  534. Node.initialized = true;
  535. }
  536. this.init();
  537. };
  538. // TODO: we may convert a lot of computation into a web worker
  539. // https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
  540. function checkParticulesCollisions(){
  541. // do not run particule collision every frames
  542. if(check_parts_colid_tick < check_parts_colid_frq){
  543. check_parts_colid_tick++;
  544. return;
  545. }
  546. check_parts_colid_tick = 1;
  547. // pre create vars to save memory;
  548. var na,nb,
  549. ma,mb,
  550. w,h,dx,dy,
  551. makeup,
  552. newVelX1, newVelY1, newVelX2, newVelY2,
  553. Smamb;
  554. // , angle;
  555. // colisions between _particules
  556. for (var n = 0, l = _nodes.length; n < l; n++) {
  557. na = _nodes[n];
  558. // avoid colliding for scrambling nodes
  559. // avoid colliding for aside nodes
  560. // avoid colliding for centered nodes
  561. if(na.scrambling || na.aside ) continue; //|| na.center
  562. ma = na.p.mass;
  563. for (var q = n+1; q < l; q++) {
  564. nb = _nodes[q];
  565. // avoid impact between center and aside particules
  566. // if((na.center && nb.aside) || (na.aside && nb.center))
  567. // and between aside particules
  568. if(nb.aside)
  569. continue;
  570. // avoid impact between two centered particulses that comes to the center
  571. if(na.center && nb.center){
  572. if(Math.min(na.p.distanceTo(_attracter), nb.p.distanceTo(_attracter)) > 300){
  573. if( Math.random()>0.3 ) continue;
  574. }
  575. }
  576. w = h = (na.r+nb.r);
  577. // if(!na.aside && !nb.aside){
  578. w = h += 4; // add a saftey zone around squares eccept for aside squares
  579. // }
  580. // if both dx and dy are inferior to w & h so squares are colliding (overlapping)
  581. // if( Math.abs(dx) <= w && Math.abs(dy) <= h){ console.log('colliding'); }
  582. // else not so skip
  583. // if( Math.abs(dx) > w || Math.abs(dy) > h) continue;
  584. dx = na.p.position.x - nb.p.position.x;
  585. if( Math.abs(dx) > w ) continue;
  586. dy = na.p.position.y - nb.p.position.y;
  587. if(Math.abs(dy) > h) continue
  588. mb = nb.p.mass;
  589. Smamb = ma+mb;
  590. if(Math.abs(dx) < Math.abs(dy)){ // vertical collision
  591. makeup = (h - Math.abs(dy))/2;
  592. if(dy > 0){ // a is upper than b
  593. na.p.position.y += makeup;
  594. nb.p.position.y -= makeup;
  595. }else{ // b is upper than a
  596. na.p.position.y -= makeup;
  597. nb.p.position.y += makeup;
  598. }
  599. // bounce
  600. // https://en.wikipedia.org/wiki/Elastic_collision#One-dimensional_Newtonian
  601. newVelY1 = (ma-mb)/Smamb*na.p.velocity.y+2*mb/Smamb*nb.p.velocity.y;
  602. newVelY2 = (mb-ma)/Smamb*nb.p.velocity.y+2*ma/Smamb*na.p.velocity.y;
  603. na.p.velocity.y = newVelY1;
  604. nb.p.velocity.y = newVelY2;
  605. }else{ // horizontal collision
  606. makeup = (w - Math.abs(dx))/2;
  607. if(dx > 0){ // a is at left of b
  608. na.p.position.x += makeup;
  609. nb.p.position.x -= makeup;
  610. }else{ // b is at left of a
  611. na.p.position.x -= makeup;
  612. nb.p.position.x += makeup;
  613. }
  614. // bounce
  615. // https://en.wikipedia.org/wiki/Elastic_collision#One-dimensional_Newtonian
  616. newVelX1 = (ma-mb)/Smamb*na.p.velocity.x+2*mb/Smamb*nb.p.velocity.x;
  617. newVelX2 = (mb-ma)/Smamb*nb.p.velocity.x+2*ma/Smamb*na.p.velocity.x;
  618. na.p.velocity.x = newVelX1;
  619. nb.p.velocity.x = newVelX2;
  620. }
  621. // slow down particule on impact
  622. // na.p.velocity.multiplyScalar(na.center && na.p.velocity.length() < 1 ? 1.1 : 0.90);
  623. // nb.p.velocity.multiplyScalar(nb.center && nb.p.velocity.length() < 1 ? 1.1 : 0.90);
  624. na.p.velocity.multiplyScalar(0.90);
  625. nb.p.velocity.multiplyScalar(0.90);
  626. }
  627. }
  628. };
  629. // show opened audio node
  630. function openNodeByNid(nid){
  631. // console.log('Corpus openNode()', nid);
  632. closeNode();
  633. if(typeof _nodes_Nid_Id[nid] != 'undefined'){
  634. // console.log('node exists');
  635. _node_opened_id = _nodes_Nid_Id[nid];
  636. _nodes[_nodes_Nid_Id[nid]].open();
  637. }
  638. }
  639. function closeNode(){
  640. if(_node_opened_id != -1){
  641. // if(typeof _nodes[_node_opened_id] !== 'undefined'){
  642. _nodes[_node_opened_id].close();
  643. // }
  644. _node_opened_id = -1;
  645. }
  646. }
  647. function createNodesRepulsions(){
  648. // how to delete all these attractions before creates new once
  649. //console.log('_nodes_centered', _nodes_centered);
  650. purgeNodesRepulsions();
  651. for (var n = 0; n < _nodes_centered.length; n++) {
  652. for (var q = n+1; q < _nodes_centered.length; q++) {
  653. _physics.makeAttraction(_nodes_centered[n].p, _nodes_centered[q].p, -0.4, 10);
  654. }
  655. }
  656. };
  657. function purgeNodesRepulsions(){
  658. // console.log('_physics.attractions.length', _physics.attractions.length);
  659. for (var a = _physics.attractions.length-1; a >= 0; a--) {
  660. // assuming that only nodes repulsions have constant < 1
  661. // and are all at the end of array
  662. if(Math.abs(_physics.attractions[a].constant) < 1){
  663. _physics.attractions.splice(a,1);
  664. }else{
  665. break;
  666. }
  667. }
  668. // console.log('_physics.attractions.length', _physics.attractions.length);
  669. };
  670. // ___ _ _ _ ____
  671. // | __|_ _____| |_ _| |_(_)___ _ _ |_ /___ _ _ ___
  672. // | _|\ V / _ \ | || | _| / _ \ ' \ / // _ \ ' \/ -_)
  673. // |___|\_/\___/_|\_,_|\__|_\___/_||_| /___\___/_||_\___|
  674. function moveEvolutionZone(l, r){
  675. var left = l || 0;
  676. var right = r || 0;
  677. console.log("moveEvolutionZone",left,right);
  678. console.log("_scene_props", _scene_props);
  679. _evolution_zone.left =
  680. left == 0
  681. ? left+20
  682. : Math.max(_scene_props.width/5, left+20);
  683. _evolution_zone.right =
  684. right == 0
  685. ? _scene_props.width-right+20
  686. : Math.min(_scene_props.width - _scene_props.width/5, _scene_props.width-right+20);
  687. _evolution_zone.center = _evolution_zone.left + (_evolution_zone.right - _evolution_zone.left)/2;
  688. console.log("moveEvolutionZone",_evolution_zone);
  689. // move _attracter to the center of the zone
  690. resizePhysics();
  691. }
  692. // ___ _ ___ _ _ _ _
  693. // | _ \__ _ _ _ __| |___ _ __ | _ \ |__ _ _ _| (_)__| |_
  694. // | / _` | ' \/ _` / _ \ ' \ | _/ / _` | || | | (_-< _|
  695. // |_|_\__,_|_||_\__,_\___/_|_|_| |_| |_\__,_|\_, |_|_/__/\__|
  696. // |__/
  697. function updateRandomPlaylist(p){
  698. _$canvas.trigger({
  699. type:'update-random-playlist',
  700. playlist:p
  701. })
  702. };
  703. // ___ _
  704. // | __|_ _| |_ _ _ ___ ___ ___
  705. // | _|| ' \ _| '_/ -_) -_|_-<
  706. // |___|_||_\__|_| \___\___/__/
  707. function toggleEntree(tid, bubbling){
  708. var $link = _$entrees_block_termlinks.filter('[tid="'+tid+'"]');
  709. var $li = $link.parents('li');
  710. var sys_path = $link.attr('data-drupal-link-system-path');
  711. var url = $link.attr('href');
  712. var title = $link.text();
  713. if(!$li.is('.opened')){
  714. _$entrees_block_termlinks.parents('li').removeClass('opened');
  715. $li.addClass('opened');
  716. $li.parents('.item-list').addClass('opened')
  717. filterEntree(tid);
  718. if(bubbling){
  719. _$body.trigger({
  720. 'type':'open_entree',
  721. 'tid':tid,
  722. 'url':url,
  723. 'sys_path':sys_path,
  724. 'title':title
  725. });
  726. }
  727. // bubbling is true only when event is a real click on entree link
  728. }else if(bubbling){
  729. $li.removeClass('opened');
  730. $li.parents('.item-list').removeClass('opened')
  731. scrambleCollection();
  732. _$body.trigger({'type':'close_entree', 'tid':tid});
  733. }
  734. };
  735. function filterEntree(t){
  736. // shutDownArticles();
  737. _nodes_centered = [];
  738. for (var n = 0; n < _nodes.length; n++) {
  739. if(_nodes[n].entrees.indexOf(t) == -1){
  740. _nodes[n].setAside();
  741. }else{
  742. _nodes[n].setCenteredOnEntree(t);
  743. // record centered nodes for inter node repulsions
  744. _nodes_centered.push(_nodes[n]);
  745. }
  746. }
  747. updateRandomPlaylist(_nodes_centered);
  748. createNodesRepulsions();
  749. };
  750. function highlightEntries(){
  751. _$entrees_block_termlinks
  752. .parents('li').removeClass('highlighted')
  753. .parents('.item-list').removeClass('highlighted');
  754. var id = -1;
  755. if(_node_hover_id != -1){
  756. id = _node_hover_id;
  757. }else if(_node_opened_id != -1){
  758. id = _node_opened_id;
  759. }
  760. var entree;
  761. if(id != -1){
  762. for (var i = 0; i < _nodes[id].entrees.length; i++) {
  763. entree = _nodes[id].entrees[i];
  764. _$entrees_block_termlinks.filter(function(){
  765. return $(this).attr('tid') == entree;
  766. }).parents('li').addClass('highlighted')
  767. .parents('.item-list').addClass('highlighted');
  768. }
  769. }
  770. };
  771. // ___ _
  772. // / __| ___ __ _ _ _ __| |_
  773. // \__ \/ -_) _` | '_/ _| ' \
  774. // |___/\___\__,_|_| \__|_||_|
  775. // and ajax modal content filtering
  776. function filterByNids(nids){
  777. // shutDownArticles();
  778. _nodes_centered = [];
  779. for (var n = 0; n < _nodes.length; n++) {
  780. if(nids.indexOf(_nodes[n].nid) == -1){
  781. _nodes[n].setAside();
  782. }else{
  783. _nodes[n].setCentered();
  784. // record centered nodes for inter node repulsions
  785. _nodes_centered.push(_nodes[n]);
  786. }
  787. }
  788. updateRandomPlaylist(_nodes_centered);
  789. createNodesRepulsions();
  790. };
  791. // ___ _ _ _
  792. // / __| __ _ _ __ _ _ __ | |__| (_)_ _ __ _
  793. // \__ \/ _| '_/ _` | ' \| '_ \ | | ' \/ _` |
  794. // |___/\__|_| \__,_|_|_|_|_.__/_|_|_||_\__, |
  795. // |___/
  796. // function resolveNormalPosAllNodes(){
  797. // console.log('resolveNormalPosAllNodes');
  798. // for (var i = 0; i < _nodes.length; i++) {
  799. // _nodes[i].resolveNormalPos();
  800. // }
  801. // };
  802. function scrambleCollection(){
  803. console.log('Corpus scrambleCollection');
  804. for (var i = 0; i < _nodes.length; i++) {
  805. _nodes[i].scramble();
  806. }
  807. updateRandomPlaylist(_playlist);
  808. // setTimeout(stopScrambling, 2000);
  809. // stopScrambling();
  810. };
  811. function closeAllEntries(){
  812. _$entrees_block_termlinks.each(function(index, el) {
  813. if($(this).parents('li').is('.opened')){
  814. $(this).trigger('click');
  815. return false;
  816. }
  817. });
  818. };
  819. // _ _ _ _
  820. // /_\ _ _| |_(_)__| |___ ___
  821. // / _ \| '_| _| / _| / -_|_-<
  822. // /_/ \_\_| \__|_\__|_\___/__/
  823. function initArtilesLink(){
  824. // add "articles link to blockentrees"
  825. var href = window.location.origin + drupalSettings.path.baseUrl +_settings.articlesindex_url;
  826. _$articles_link = $('<a>')
  827. .html('Articles')
  828. .attr("href", href)
  829. .attr("data-drupal-link-system-path", _settings.articlesindex_url)
  830. .addClass('articles-link ajax-link');
  831. // main.js from template will load the index then trigger the filter here
  832. // .on('click', onCLickedOnArticles);
  833. $('.item-list ul',_$entrees_block).append(
  834. $('<li>').append(
  835. $('<span class="oblique-wrapper">').append(_$articles_link)
  836. )
  837. );
  838. };
  839. // function onCLickedOnArticles(e){
  840. // e.preventDefault();
  841. // $(this).toggleClass('is-active');
  842. // if($(this).is('.is-active')){
  843. // activateArticlesFilter();
  844. // closeAllEntries();
  845. // }else{
  846. // deactivateArticlesFilter();
  847. // }
  848. // // _$canvas.trigger({
  849. // // 'type':'corpus-cliqued-on-articles'
  850. // // });
  851. // return false;
  852. // };
  853. // function activateArticlesFilter(){
  854. // //console.log('activateArticlesFilter');
  855. // _articles_filter_on = true;
  856. // // OPTION 1 : just fade no article nodes
  857. // // for (var i = 0; i < _no_articles_nodes.length; i++) {
  858. // // _no_articles_nodes[i].fade();
  859. // // }
  860. // // END OPTION 1
  861. //
  862. // // OPTION 2 : center the articles nodes and aside others
  863. // closeAllEntries();
  864. // _nodes_centered = [];
  865. // for (var i = 0; i < _articles_nodes.length; i++) {
  866. // _articles_nodes[i].setCentered();
  867. // // record centered nodes for inter node repulsions
  868. // _nodes_centered.push(_articles_nodes[i]);
  869. // }
  870. // for (var i = 0; i < _no_articles_nodes.length; i++) {
  871. // _no_articles_nodes[i].setAside();
  872. // }
  873. // // TODO: open an index of nodes with articles
  874. // // loadArticlesIndex();
  875. // // END OPTION 2
  876. //
  877. // updateRandomPlaylist(_articles_nodes);
  878. // if(typeof _paq !== 'undefined'){
  879. // // trackEvent(category, action, [name], [value])
  880. // _paq.push(['trackEvent', 'Corpus Articles', 'on']);
  881. // }
  882. // };
  883. // function loadArticlesIndex(){
  884. // var path = window.location.origin + drupalSettings.path.baseUrl +_settings.articlesindex_url+'/ajax';
  885. // $.getJSON(path)
  886. // .done(function(data){
  887. // onArticlesIndexLoaded(data);
  888. // })
  889. // .fail(function(jqxhr, textStatus, error){
  890. // onArticlesIndexLoadFail(jqxhr, textStatus, error);
  891. // });
  892. // };
  893. //
  894. // function onArticlesIndexLoaded(data){
  895. // // insert index col
  896. // _$container.find('main[role="main"] .row').append(data.rendered);
  897. //
  898. // // trigger event
  899. // _$body.trigger({
  900. // 'type':'articles-index-loaded',
  901. // 'results':data.results_nids
  902. // });
  903. // };
  904. //
  905. // function onArticlesIndexLoadFail(jqxhr, textStatus, error){
  906. // console.warn('EdlpCorpus : articles index ajax load failed : '+error, jqxhr.responseText);
  907. // };
  908. // function deactivateArticlesFilter(){
  909. // //console.log('deactivateArticlesFilter');
  910. // _articles_filter_on = false;
  911. //
  912. // // OPTION 1 : just fade no article nodes
  913. // // for (var i = 0; i < _no_articles_nodes.length; i++) {
  914. // // _no_articles_nodes[i].unFade();
  915. // // }
  916. //
  917. // // OPTION 2 : centered / aside
  918. // scrambleCollection();
  919. //
  920. // updateRandomPlaylist(_playlist);
  921. // if(typeof _paq !== 'undefined'){
  922. // // trackEvent(category, action, [name], [value])
  923. // _paq.push(['trackEvent', 'Corpus Articles', 'off']);
  924. // }
  925. // };
  926. // function shutDownArticles(){
  927. // shutdown articles if active
  928. // if(_$articles_link.is('.is-active'))
  929. // _$articles_link.trigger('click');
  930. // };
  931. // ___ _
  932. // | __|_ _____ _ _| |_ ___
  933. // | _|\ V / -_) ' \ _(_-<
  934. // |___|\_/\___|_||_\__/__/
  935. function initEvents(){
  936. console.log('Corpus, initEvents');
  937. _$canvas
  938. .on('mousemove', function(event) {
  939. event.preventDefault();
  940. _m_pos.x = event.originalEvent.clientX;
  941. _m_pos.y = event.originalEvent.clientY;
  942. })
  943. .on('mouseenter', function(event){
  944. // console.log('onMouseIN');
  945. _mouse_in = true;
  946. })
  947. .on('mouseout', function(event){
  948. // console.log('onMouseOUT');
  949. _mouse_in = false;
  950. _node_pop_up.removeNode();
  951. })
  952. .on('click', function(event) {
  953. if(event.target.tagName != "A" && event.target.tagName != "INPUT"){
  954. // console.log("Corpus : click");
  955. event.preventDefault();
  956. if(_node_hover_id != -1){
  957. // console.log("corpus : click on node", _nodes[_node_hover_id]);
  958. var event = {
  959. 'type':'corpus-cliked-on-node',
  960. 'target_node':_nodes[_node_hover_id],
  961. // 'article':_articles_filter_on
  962. };
  963. _$canvas.trigger(event);
  964. // instead of directly opening the doc, create an event listener (e.g. : audio played from random)
  965. // openNode(_node_hover_id);
  966. }else{
  967. // console.log('corpus : click on map');
  968. _$canvas.trigger('corpus-cliked-on-map');
  969. // shutDownArticles();
  970. }
  971. }
  972. })
  973. .on('mouseover-audio-link', function(e){
  974. console.log("Corpus on mouseover-audio-link", e);
  975. // _node_hover_id = _nodes_Nid_Id[e.nid];
  976. // _node_pop_up.setNode(_nodes_by_nid[e.nid]);
  977. _nodes_by_nid[e.nid].setHover();
  978. })
  979. .on('mouseout-audio-link', function(e){
  980. console.log("Corpus on mouseover-audio-link", e);
  981. // _node_hover_id = -1;
  982. // _node_pop_up.removeNode();
  983. _nodes_by_nid[e.nid].unsetHover();
  984. })
  985. .on('audio-node-opened', function(e){
  986. // console.log('Corpus audio-node-opened', e);
  987. openNodeByNid(e.nid);
  988. })
  989. .on('audio-node-closed', function(e){
  990. closeNode();
  991. })
  992. .on('open-entree', function(e){
  993. toggleEntree(e.tid);
  994. })
  995. .on('close-all-entree', function(e){
  996. closeAllEntries();
  997. })
  998. .on('scramble-collection', function(e){
  999. console.log('scramble-collection', e);
  1000. // resolveNormalPosAllNodes();
  1001. scrambleCollection();
  1002. })
  1003. .on('shuffle-collection', function(e){
  1004. console.log('shuffle-collection', e);
  1005. onResizeCanvas();
  1006. });
  1007. _$entrees_block_termlinks.on('click', function(event) {
  1008. // console.log('_$entrees_block_termlinks click', this);
  1009. event.preventDefault();
  1010. toggleEntree($(this).attr('tid'), true);
  1011. // var $link = $(this);
  1012. // var tid = $link.attr('tid');
  1013. // var $li = $link.parents('li');
  1014. // var sys_path = $link.attr('data-drupal-link-system-path');
  1015. // var url = $link.attr('href');
  1016. // if(!$li.is('.opened')){
  1017. // _$entrees_block_termlinks.parents('li').removeClass('opened');
  1018. // $li.addClass('opened');
  1019. // toggleEntree(tid);
  1020. // _$body.trigger({'type':'open_entree', 'tid':tid, 'url':url, 'sys_path':sys_path});
  1021. // }else{
  1022. // $li.removeClass('opened');
  1023. // scrambleCollection();
  1024. // _$body.trigger({'type':'close_entree', 'tid':tid});
  1025. // }
  1026. return false;
  1027. });
  1028. _$body
  1029. .on('chutier-action-done', function(e) {
  1030. _nodes_by_nid[e.target_id].chutier_action = e.new_action;
  1031. })
  1032. .on('ajax-node-loaded-linked-documents', function(e){
  1033. console.log("Edlp Corpus, ajax-node-loaded-linked-documents",e.nids);
  1034. // filter map's nodes
  1035. filterByNids(e.nids);
  1036. })
  1037. .on('search-results-loaded', function(e){
  1038. //console.log("Edlp Corpus, search-results-loaded",e.results);
  1039. // filter map's nodes
  1040. filterByNids(e.results);
  1041. })
  1042. .on('search-closed', function(e){
  1043. scrambleCollection();
  1044. })
  1045. .on('new-content-not-entree-ajax-loaded', function(e){
  1046. // close all entries only if entry already opened
  1047. // TODO: user the function close all entries ?
  1048. // closeAllEntries(); not working, is closing also the ajax loaded content
  1049. if(_$entrees_block_termlinks.parents('li.opened').length){
  1050. _$entrees_block_termlinks
  1051. .parents('li').removeClass('opened')
  1052. .parents('.item-list').removeClass('opened');
  1053. scrambleCollection();
  1054. }
  1055. })
  1056. .on('visible-space-changed', function(e){
  1057. // limits are absolute distance from each side (not positions from left)
  1058. moveEvolutionZone(e.left_limit, e.right_limit);
  1059. });
  1060. };
  1061. function checkPreOpenedEntry(){
  1062. _$entrees_block.find('li.entree').each(function(index, el) {
  1063. var $li = $(this);
  1064. if($('a.is-active', $li).length){
  1065. $li.addClass('opened')
  1066. .parents('.item-list').addClass('opened');
  1067. filterEntree($li.attr('tid'));
  1068. return false;
  1069. }
  1070. });
  1071. };
  1072. // _ _ _ ___ _ _
  1073. // | \| |___ __| |___| _ \___ _ __| | | |_ __
  1074. // | .` / _ \/ _` / -_) _/ _ \ '_ \ |_| | '_ \
  1075. // |_|\_\___/\__,_\___|_| \___/ .__/\___/| .__/
  1076. // |_| |_|
  1077. function initNodePopup(){
  1078. _node_pop_up = new NodePopUp();
  1079. };
  1080. function NodePopUp(){
  1081. this.visible = false;
  1082. this.node;
  1083. this.$dom = $('<div>')
  1084. .addClass('node-popup')
  1085. .attr('pos', 'top-right')
  1086. .appendTo('body');
  1087. this.$content = $('<div>').addClass('inner').appendTo(this.$dom);
  1088. if (typeof NodePopUp.initialized == "undefined") {
  1089. NodePopUp.prototype.setNode = function(n){
  1090. // console.log('NodePopUp setNode()');
  1091. this.node = n;
  1092. // positioning NodePopUp regarding node position
  1093. this.setPositioning();
  1094. // update NodePopUp content
  1095. this.setContent();
  1096. };
  1097. NodePopUp.prototype.setPositioning = function(){
  1098. // switch(true){
  1099. // case this.node.x > this.node.wall_limits.right-350-_evolution_zone.right && this.node.y < this.node.wall_limits.top+200:
  1100. // this.$dom.attr('pos', 'bottom-left');
  1101. // break;
  1102. // case this.node.x > this.node.wall_limits.right-350-_evolution_zone.right:
  1103. // this.$dom.attr('pos', 'top-left');
  1104. // break;
  1105. // case this.node.y < this.node.wall_limits.top+200:
  1106. // this.$dom.attr('pos', 'bottom-right');
  1107. // break;
  1108. // default:
  1109. // this.$dom.attr('pos', 'top-right');
  1110. // }
  1111. switch(true){
  1112. case this.node.x > _evolution_zone.right-350 && this.node.y < this.node.wall_limits.top+200:
  1113. this.$dom.attr('pos', 'bottom-left');
  1114. break;
  1115. case this.node.x > _evolution_zone.right-350:
  1116. this.$dom.attr('pos', 'top-left');
  1117. break;
  1118. case this.node.y < this.node.wall_limits.top+200:
  1119. this.$dom.attr('pos', 'bottom-right');
  1120. break;
  1121. default:
  1122. this.$dom.attr('pos', 'top-right');
  1123. }
  1124. };
  1125. NodePopUp.prototype.setContent = function(){
  1126. // console.log(this.node);
  1127. this.$content.html('');
  1128. var $entrees = $('<div>').addClass('entrees');
  1129. for (var i = 0; i < this.node.entrees.length; i++) {
  1130. var tid = this.node.entrees[i];
  1131. $entrees.append($('<span>').addClass('entree').attr('tid', tid));
  1132. }
  1133. var $chutier_action = $('<span>').addClass('chutier-icon').attr('action', this.node.chutier_action);
  1134. this.$content
  1135. .append($entrees)
  1136. .append('<h2 class="title">'+this.node.title+'</h2>')
  1137. .append('<section class="description">'+this.node.description+'</section>')
  1138. .append($chutier_action);
  1139. };
  1140. NodePopUp.prototype.removeNode = function(){
  1141. // console.log('NodePopUp removeNode()');
  1142. this.node = false;
  1143. };
  1144. NodePopUp.prototype.draw = function(){
  1145. if(this.node){
  1146. this.$dom.css({
  1147. 'display':"block",
  1148. 'left':this.node.x+"px",
  1149. 'top':this.node.y+"px",
  1150. });
  1151. }else{
  1152. this.$dom.css({
  1153. 'display':"none",
  1154. });
  1155. }
  1156. };
  1157. NodePopUp.initialized = true;
  1158. }
  1159. }
  1160. // ___ _
  1161. // | _ \___ _ _ __| |___ _ _
  1162. // | / -_) ' \/ _` / -_) '_|
  1163. // |_|_\___|_||_\__,_\___|_|
  1164. function render(){
  1165. _ctx.clearRect(0, 0, _scene_props.width, _scene_props.height);
  1166. checkParticulesCollisions();
  1167. for (var i = 0; i < _nodes.length; i++) {
  1168. _nodes[i].onUpdate();
  1169. }
  1170. _node_pop_up.draw();
  1171. if(_node_hover_id != -1){
  1172. _canvas.style.cursor = 'pointer';
  1173. }else{
  1174. _canvas.style.cursor = 'auto';
  1175. }
  1176. // check for highlighted entries
  1177. highlightEntries();
  1178. };
  1179. // ___ _ _ _ _
  1180. // / __| |_ __ _ _ _| |_ /_\ _ _ (_)_ __ ___
  1181. // \__ \ _/ _` | '_| _|/ _ \| ' \| | ' \/ -_)
  1182. // |___/\__\__,_|_| \__/_/ \_\_||_|_|_|_|_\___|
  1183. function startAnime(){
  1184. _physics.onUpdate(render);
  1185. _physics.play()
  1186. $('body')
  1187. .attr('corpus', 'map-ready')
  1188. .trigger({
  1189. 'type':'corpus-map-ready',
  1190. 'playlist':_playlist
  1191. });
  1192. };
  1193. init();
  1194. }
  1195. $(document).ready(function($) {
  1196. console.log("Corpus ready");
  1197. if(drupalSettings.path.isFront && !edlp_mobile.device_is_mobile){
  1198. console.log("Corpus new edlpCorpus()");
  1199. var edlpcorpus = new EdlpCorpus();
  1200. }
  1201. });
  1202. })(jQuery, Drupal, drupalSettings);