jee.js 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. /*
  2. _ _
  3. |_|___ _ _ ___ ___ ___ ___| |_ ___ ___ ___ ___ ___ ___ ___
  4. | | -_| | | | -_|_ -| | -_| _| | -_| | . | .'| . | -_|_ -|
  5. _| |___|___|_|_|___|___| |___|_| |___|_|_|_ |__,|_ |___|___|
  6. |___| |___| |___|
  7. Bachir Soussi Chiadmi
  8. 2015
  9. */
  10. jQuery(document).ready(function($) {
  11. console.log('Hello Jee');
  12. var _debug = true,
  13. _avgDelay = 1,
  14. _lastDraw = new Date,
  15. _fps,
  16. _$nav_cursor;
  17. var _$body = $('body'),
  18. _$header = $("#header"),
  19. _$chapitres = $('.node-chapitre', '#main'),
  20. _chapitres_len = _$chapitres.length,
  21. _chapters = [],
  22. _$container = $('#main'),
  23. _container = {
  24. w:_$container.width(),
  25. h:_$container.height()
  26. },
  27. _center = {x:_container.w/2,y:_container.h/2},
  28. _nav_pos = {x:0, y:0},
  29. _mouse_down_pos = {x:0,y:0},
  30. _prev_mouse_pos = {x:0,y:0},
  31. _fps = 1000/12,
  32. _dragging = false, _timeout_dragging;
  33. var _$chapter_wrapper = $('<div>').attr('id', 'chapter-wrapper').appendTo(_$container),
  34. _loaded_chapter = false;
  35. var _bubbles = new Array(),
  36. _stars = new Array();
  37. var _$footer = $('#footer'),
  38. _$static_wrapper = $('<div><div class="inner"></div></div>').attr('id', 'static-wrapper').appendTo(_$container),
  39. _$close_static = $('<div>').addClass('close').appendTo(_$static_wrapper);
  40. _loaded_static = false;
  41. var _$loader = $('<div>').attr('id','loader').appendTo(_$body);
  42. function init(){
  43. if(_debug)
  44. initDebug();
  45. initChapterWrapper();
  46. initChapters();
  47. initStaticLinks();
  48. launchNav();
  49. // FULL SCREEN
  50. var $fullscreenBtn = $('<div>Plein écran</div>').attr('id','fullscreen-btn').appendTo("#root");
  51. $fullscreenBtn.on('click', onFullScreen);
  52. // create bubbles
  53. for (var i = 2; i > 0; i--) {
  54. _bubbles.push($('<div>').addClass('bubble bubble-'+i).prependTo(_$container));
  55. };
  56. // create stars
  57. // for (var i = 20; i > 0; i--) {
  58. // _stars.push(
  59. // $('<div>')
  60. // .addClass('star star-'+i)
  61. // .css({
  62. // left:randB(-400, _container.w+400),
  63. // top:randB(-400, _container.h+400)
  64. // })
  65. // .prependTo(_$container)
  66. // );
  67. // };
  68. };
  69. function initDebug(){
  70. $('<p>').attr('id', 'fps').appendTo(_$container);
  71. _fps = document.getElementById('fps');
  72. requestAnimationFrame(displayFps);
  73. _$nav_cursor = $('<div id="nav-cursor"></div>').appendTo(_$container);
  74. moveDebugCursor();
  75. };
  76. function displayFps(){
  77. requestAnimationFrame(displayFps);
  78. var now = new Date;
  79. var delay = now - _lastDraw;
  80. _avgDelay += (delay - _avgDelay) / 10;
  81. _lastDraw = now;
  82. _fps.innerHTML = (1000/_avgDelay).toFixed(1) + " fps";
  83. };
  84. function moveDebugCursor(){
  85. _$nav_cursor.css({
  86. left:_nav_pos.x+_center.x+"px",
  87. top:_nav_pos.y+_center.y+"px"
  88. });
  89. };
  90. function initChapterWrapper(){
  91. $('<div id="home-btn">')
  92. .on("click", closeChapterWrapper)
  93. .appendTo(_$chapter_wrapper);
  94. };
  95. function closeChapterWrapper(e){
  96. _loaded_chapter = false;
  97. _$chapter_wrapper.removeClass('visible');
  98. _$body.removeClass('chapter-displayed');
  99. };
  100. function initChapters(){
  101. // Place each chapters on the ellipse contained on the screen
  102. var base_a = Math.random() *360;
  103. _$chapitres.each(function(i, e) {
  104. // Lets create the chapter object and place him self
  105. _chapters.push(new Chapter(i, e, base_a));
  106. });
  107. };
  108. function launchNav(){
  109. $(document)
  110. /*
  111. ____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____
  112. | \| __| __| | |_ _| | _ | | __| | | __| | |_ _| __|
  113. | | | __|__ | -| | | | | | __| | __| | | __| | | | | | |__ |
  114. |____/|_____|_____|__|__| |_| |_____|__| |_____|\___/|_____|_|___| |_| |_____|
  115. */
  116. .bind('mousedown', function(e){
  117. console.log('document mousedown');
  118. clearTimeout(_timeout_dragging);
  119. if(_loaded_chapter || _loaded_static)
  120. return false;
  121. // set initial cursor pos
  122. _mouse_down_pos.x = e.clientX;
  123. _mouse_down_pos.y = e.clientY;
  124. updateNavPos(e.clientX, e.clientY, true);
  125. $(this).bind('mousemove', function(e){
  126. console.log('document mousemove');
  127. updateNavPos(e.clientX, e.clientY, false);
  128. });
  129. // activate dragging if already activated
  130. if(!_dragging){
  131. _dragging = true;
  132. startMoveNav();
  133. }
  134. })
  135. .bind('mouseup', function(e){
  136. console.log('document mouseup');
  137. if(_loaded_chapter || _loaded_static)
  138. return false;
  139. stopMoveNav();
  140. $(this).unbind('mousemove');
  141. // close all preview
  142. if(Math.abs(e.clientX - _mouse_down_pos.x) < 2
  143. && Math.abs(e.clientY - _mouse_down_pos.y) < 2)
  144. for (var i = _chapitres_len - 1; i >= 0; i--)
  145. _chapters[i].closePreview().unMitigate();
  146. })
  147. /*
  148. _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____
  149. |_ _| | | | | | | | __| | | __| | |_ _| __|
  150. | | | | | | | --| | | __| | | __| | | | | | |__ |
  151. |_| |_____|_____|_____|__|__| |_____|\___/|_____|_|___| |_| |_____|
  152. */
  153. .bind('document touchstart', function(e){
  154. console.log('touchstart');
  155. clearTimeout(_timeout_dragging);
  156. if(_loaded_chapter || _loaded_static)
  157. return false;
  158. // set initial pos
  159. updateNavPos(e.originalEvent.touches[0].clientX, e.originalEvent.touches[0].clientY, true);
  160. // activate dragging if already activated
  161. if(!_dragging){
  162. _dragging = true;
  163. startMoveNav();
  164. }
  165. })
  166. .bind('touchmove', function(e){
  167. console.log('document touchmove');
  168. if(_loaded_chapter || _loaded_static)
  169. return false;
  170. updateNavPos(e.originalEvent.touches[0].clientX, e.originalEvent.touches[0].clientY, false);
  171. })
  172. .bind('touchend', function(e){
  173. console.log("document touchend");
  174. if(_loaded_chapter || _loaded_static)
  175. return false;
  176. stopMoveNav();
  177. });
  178. // TODO : nav on scroll events
  179. };
  180. function updateNavPos(x,y,init){
  181. if(!init){
  182. _nav_pos.x += x - _prev_mouse_pos.x;
  183. _nav_pos.y += y - _prev_mouse_pos.y;
  184. // constrain nav pos on container
  185. _nav_pos.x = _nav_pos.x < -_center.x*2
  186. ? -_center.x*2
  187. : _nav_pos.x > _center.x*2
  188. ? _center.x*2
  189. : _nav_pos.x;
  190. _nav_pos.y = _nav_pos.y < -_center.y*2
  191. ? -_center.y*2
  192. : _nav_pos.y > _center.y*2
  193. ? _center.y*2
  194. : _nav_pos.y;
  195. }
  196. _prev_mouse_pos.x = x;
  197. _prev_mouse_pos.y = y;
  198. // debuging cursor
  199. if(_debug)
  200. moveDebugCursor();
  201. };
  202. function startMoveNav(){
  203. window.requestAnimationFrame(moveNav);
  204. };
  205. function moveNav(){
  206. // console.log("moveNav");
  207. if(!_dragging) return;
  208. window.requestAnimationFrame(moveNav);
  209. // move chapters
  210. for (var i = _chapitres_len - 1; i >= 0; i--)
  211. _chapters[i].move();
  212. // move header
  213. // _$header.css({
  214. // transform:"translate3d("+(_nav_pos.x)*0.2+"px, "+(_nav_pos.y)*0.2+"px,0)"
  215. // });
  216. _$header.translate3d({x:_nav_pos.x*0.2,y:_nav_pos.y*0.2});
  217. // bubbles and stars dont move so smoothly on tablette ...
  218. // should keep it only on desktop
  219. // move bubbles
  220. // for (var i = _bubbles.length - 1; i >= 0; i--) {
  221. // _bubbles[i].translate3d({x:_nav_pos.x*0.4,y:_nav_pos.y*0.4});
  222. // };
  223. // move stars
  224. // for (var i = _stars.length - 1; i >= 0; i--) {
  225. // _stars[i].translate3d({x:_nav_pos.x*-0.3,y:_nav_pos.y*-0.3});
  226. // };
  227. };
  228. function stopMoveNav(){
  229. console.log('stopMoveNav');
  230. clearTimeout(_timeout_dragging);
  231. _timeout_dragging = setTimeout(function(){
  232. console.log("dragging stoped");
  233. _dragging = false;
  234. },3000);
  235. };
  236. function moveToChapter(chapter){
  237. // fake a mousdown by providing first pos as current pos
  238. _prev_mouse_pos.x = _nav_pos.x;
  239. _prev_mouse_pos.y = _nav_pos.y;
  240. // calculate the second pos of faked mousemove
  241. var xl = _center.x - chapter.pos.x - chapter.geom.w/2;
  242. var yl = 100 - chapter.pos.y;
  243. updateNavPos(xl, yl, false);
  244. startMoveNav();
  245. stopMoveNav();
  246. };
  247. function onFullScreen(e){
  248. if(_$body.is('fullscreen')){
  249. exitFullscreen();
  250. _$body.removeClass('fullscreen');
  251. }else{
  252. launchIntoFullscreen(document.getElementById("root"));
  253. _$body.addClass('fullscreen');
  254. }
  255. if(_loaded_chapter)
  256. setTimeout(_loaded_chapter.buildVideos(), 100);
  257. };
  258. function initStaticLinks(){
  259. $('ul.menu a', _$footer).on('click', onClickStaticLink);
  260. _$close_static.on('click', onCloseStatic);
  261. };
  262. function onClickStaticLink(e){
  263. e.preventDefault();
  264. _$static_wrapper.removeClass('visible');
  265. loadStaticContent($(this).attr("href"));
  266. _$body.addClass('loading');
  267. _loaded_static = true;
  268. return false;
  269. };
  270. function loadStaticContent(h){
  271. $.getJSON(
  272. '/jee/static',
  273. {"href":h},
  274. onStaticLoaded
  275. );
  276. };
  277. function onStaticLoaded(data, textstatus){
  278. console.log('data',data);
  279. displayStatic(data.node);
  280. };
  281. function displayStatic(node){
  282. _$static_wrapper.addClass('visible').find('.inner').html(node);
  283. _$body.removeClass('loading');
  284. };
  285. function onCloseStatic(e){
  286. _$static_wrapper.removeClass('visible');
  287. };
  288. /*
  289. ________ __
  290. / ____/ /_ ____ _____ / /____ _____
  291. / / / __ \/ __ `/ __ \/ __/ _ \/ ___/
  292. / /___/ / / / /_/ / /_/ / /_/ __/ /
  293. \____/_/ /_/\__,_/ .___/\__/\___/_/
  294. /_/
  295. */
  296. function Chapter(i, e, base_a){
  297. // $e.obj = this;
  298. this.i = i;
  299. this.e = e;
  300. this.$e = $(e);
  301. this.nid = this.$e.attr("id").match(/^node-(\d+)/)[1];
  302. this.geom = {
  303. base_a:base_a,
  304. a:0,
  305. r:0,
  306. w:this.$e.outerWidth(true),
  307. h:this.$e.outerHeight(true)
  308. }
  309. this.pos = {x:0,y:0};
  310. this.trans = {x:0, y:0,z:0};
  311. this.ease = randB(0.05, 0.3);
  312. //drifting
  313. this.$title = $('h2.node-title', this.$e);
  314. this.$content = $('.content:first', this.$e);
  315. this.title_x = 0;
  316. this.content_x = 0;
  317. this.drifting_direction = Math.random()-0.5 > 0 ? 1 : -1;
  318. this.drifting_time = null;
  319. //preview
  320. this.is_previewed = false;
  321. //mitigate
  322. this.is_mitigated = false;
  323. //parties
  324. this.$parties = $('.field-name-field-partie', e);
  325. this.parts_pos = {xs:new Array(), ys:new Array()};
  326. this.lines = new Array();
  327. this.linesAnimeStartTime = 0,
  328. this.linesAnimeDuration = 2000; // milli sec
  329. // chapter
  330. this.$n = false;
  331. this.$blocks = false;
  332. this.$vids_container = false;
  333. this.$vids = false;
  334. this.texts_pos = shuffleArray([1,2,3]);
  335. this.dimvideo = {w:0, h:0};
  336. this.$slider = null;
  337. this.cur_vid_playing = 0;
  338. // prototypes
  339. if (typeof Chapter.initialized == "undefined") {
  340. Chapter.prototype.init = function(){
  341. this.setInitPos();
  342. this.drawLines();
  343. this.setEvents();
  344. this.initDrifiting();
  345. // enable nodes after intro anime
  346. setTimeout(
  347. (function(t){
  348. return function(){
  349. t.$e.addClass('enabled');
  350. }
  351. }(this)),
  352. randB(5000, 8000));
  353. };
  354. Chapter.prototype.setInitPos = function(){
  355. // distribute elements arround the center
  356. this.geom.a = (360/_chapitres_len*this.i+this.geom.base_a)*Math.PI/180;
  357. // console.log("Chapter :: setInitPos", this.$e);
  358. this.geom.c = Math.cos(this.geom.a);
  359. this.geom.s = Math.sin(this.geom.a);
  360. this.geom.abs_c = Math.abs(this.geom.c);
  361. this.geom.abs_s = Math.abs(this.geom.s);
  362. if (this.geom.abs_c * _container.h > this.geom.abs_s * _container.w) {
  363. // It crosses left or right side
  364. this.geom.r = (_center.x / this.geom.abs_c)*0.5;
  365. }else {
  366. // Top or bottom side
  367. this.geom.r = (_center.y / this.geom.abs_s)*0.5;
  368. }
  369. // change randomly radius
  370. if(this.i%2){
  371. this.geom.r = randB(this.geom.r*1.5, this.geom.r*2);
  372. }else{
  373. this.geom.r = randB(this.geom.r*0.8, this.geom.r*1.5);
  374. }
  375. this.pos.x = Math.round(_center.x+this.geom.r * this.geom.c) - this.geom.w/2;
  376. this.pos.y = Math.round(_center.y+this.geom.r * -this.geom.s) - this.geom.h/2;
  377. console.log('this', this);
  378. this.$e.css({
  379. left:this.pos.x,
  380. top:this.pos.y
  381. });
  382. };
  383. Chapter.prototype.setEvents = function(){
  384. //http://technify.me/user-experience/javascript/jquery/trigger-custom-events-with-jquery/
  385. // click to preview chapter
  386. $('h2.node-title, .field-name-field-partie:first>.field-name-field-vignette', this.$e)
  387. .on('click', this, function(e){
  388. // e.stopImmediatePropagation();
  389. e.stopPropagation();
  390. e.preventDefault();
  391. e.data.preview(e);
  392. return false;
  393. });
  394. $('.links a', this.$e)
  395. .on('click', this, function(e){
  396. e.stopPropagation();
  397. e.preventDefault();
  398. e.data.loadNode();
  399. return false;
  400. });
  401. };
  402. Chapter.prototype.initDrifiting = function(){
  403. // an other option could be to drift the whole page with the same engine than draging
  404. requestAnimationFrame(this.drift.bind(this));
  405. };
  406. Chapter.prototype.drift = function(timestamp){
  407. requestAnimationFrame(this.drift.bind(this));
  408. var now = new Date().getTime(),
  409. dt = now - (this.drifting_time || now);
  410. this.drifting_time = now;
  411. if(!this.is_previewed){
  412. this.title_x += (10/1000)*dt*this.drifting_direction;
  413. this.content_x += (6/1000)*dt*this.drifting_direction;
  414. this.drifting_direction =
  415. this.content_x > randB(100,130)
  416. ? -1
  417. : this.content_x < -randB(100,130)
  418. ? 1
  419. : this.drifting_direction;
  420. this.$title.translate3d({x:this.title_x});
  421. this.$content.translate3d({x:this.content_x});
  422. }
  423. };
  424. Chapter.prototype.move = function(){
  425. this.trans.x += (_nav_pos.x - this.trans.x)*this.ease;
  426. this.trans.y += (_nav_pos.y - this.trans.y)*this.ease;
  427. // this.trans.z = Math.floor(Math.sqrt(
  428. // Math.pow(
  429. // _center.x-(this.pos.x+this.trans.x)
  430. // ,2
  431. // )
  432. // +
  433. // Math.pow(
  434. // _center.y-(this.pos.y+this.trans.y)
  435. // ,2
  436. // )
  437. // ));
  438. // if(this.i === 0)
  439. // console.log(this.i+" this.trans.z", this.trans.z);
  440. this.$e.translate3d({x:this.trans.x,y:this.trans.y});
  441. };
  442. Chapter.prototype.preview = function(){
  443. // don't relaunch preview more that one time
  444. if(this.is_previewed) return;
  445. console.log('preview', this.i);
  446. this.unMitigate();
  447. this.is_previewed = true;
  448. // close other chapters
  449. for (var i = _chapitres_len - 1; i >= 0; i--)
  450. if(i !== this.i)
  451. _chapters[i].closePreview().mitigate();
  452. this.displayPreview();
  453. moveToChapter(this);
  454. };
  455. Chapter.prototype.displayPreview = function(e){
  456. // define randomly position of parties
  457. this.resetPartsPos();
  458. // apply new position to parties
  459. var that = this;
  460. this.$parties.each(function(i, e) {
  461. setTimeout(
  462. (function(i, e, xs, ys){
  463. return function(){
  464. $(e).translate3d({x:xs[i],y:ys[i]});
  465. }
  466. }(i, e, that.parts_pos.xs, that.parts_pos.ys)),
  467. 10);
  468. }); // each $parties
  469. this.$e.addClass('previewed');
  470. requestAnimationFrame(this.animeLines.bind(this));
  471. };
  472. Chapter.prototype.resetPartsPos = function(){
  473. this.parts_pos = {xs:new Array(), ys:new Array()};
  474. for (var i = 0; i < 2; i++) {
  475. switch(i){
  476. case 0:
  477. this.parts_pos.xs.push(randB(180,280));
  478. this.parts_pos.ys.push(randB(250,350));
  479. break;
  480. case 1:
  481. this.parts_pos.xs.push(randB(-280,-180));
  482. this.parts_pos.ys.push(randB(430,530));
  483. break;
  484. }
  485. };
  486. this.parts_pos.xs = shuffleArray(this.parts_pos.xs);
  487. this.parts_pos.ys = shuffleArray(this.parts_pos.ys);
  488. // always place the first circle on top center
  489. this.parts_pos.xs.unshift(randB(-30,30));
  490. this.parts_pos.ys.unshift(randB(120,140));
  491. };
  492. Chapter.prototype.closePreview = function(){
  493. if(!this.is_previewed) return this;
  494. this.$e.removeClass('previewed')
  495. .find('.field-name-field-partie')
  496. .css({transform:"none"});
  497. requestAnimationFrame(this.animeLines.bind(this));
  498. this.is_previewed = false;
  499. return this;
  500. };
  501. Chapter.prototype.mitigate = function(){
  502. if(this.is_mitigated) return this;
  503. this.$e.addClass('mitigated');
  504. return this;
  505. };
  506. Chapter.prototype.unMitigate = function(){
  507. if(this.is_mitigated) return this;
  508. this.$e.removeClass('mitigated');
  509. return this;
  510. };
  511. Chapter.prototype.drawLines = function(){
  512. for (var i = 0; i < 2; i++) {
  513. this.lines.push({
  514. $line:$("<div>").addClass('line', 'line-'+i).prependTo(this.$parties[i])
  515. });
  516. };
  517. };
  518. Chapter.prototype.animeLines = function(timestamp){
  519. // console.log("anime line "+this.nid);
  520. // get the time on first anime launch
  521. if(this.linesAnimeStartTime === 0)
  522. this.linesAnimeStartTime = timestamp;
  523. // limit the animation time
  524. if(timestamp - this.linesAnimeStartTime < this.linesAnimeDuration){
  525. requestAnimationFrame(this.animeLines.bind(this));
  526. }else{
  527. this.linesAnimeStartTime = 0;
  528. }
  529. // get the lines length
  530. var l, a, pos1, pos2;
  531. for (var i = 0; i < this.lines.length; i++) {
  532. pos1 = this.$parties.eq(i).position();
  533. pos2 = this.$parties.eq(i+1).position();
  534. l = Math.sqrt(
  535. Math.pow(
  536. pos2.left - pos1.left
  537. ,2
  538. )
  539. +
  540. Math.pow(
  541. pos2.top - pos1.top
  542. ,2
  543. )
  544. );
  545. // get the rotation
  546. a = 180 / 3.14 * Math.acos((pos2.top - pos1.top) / l);
  547. if(pos2.left > pos1.left)
  548. a *= -1;
  549. // console.log("a = "+a);
  550. this.lines[i].$line.css({
  551. 'height':l,
  552. transform:"rotate3d(0,0,1,"+a+"deg)"
  553. });
  554. };
  555. };
  556. // _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____
  557. // | | _ | __| | | | | | | _ | _ |_ _| __| __ |
  558. // | | | __| __| | | | | --| | | __| | | | __| -|
  559. // |_____|__| |_____|_|___| |_____|__|__|__|__|__| |_| |_____|__|__|
  560. Chapter.prototype.loadNode = function(e){
  561. // console.log("Chapter :: open : nid", this.nid);
  562. _$body.addClass('loading');
  563. $.getJSON(
  564. '/jee/chapter/'+this.nid,
  565. {},
  566. this.nodeLoaded.bind(this)
  567. );
  568. _$body.addClass('chapter-displayed');
  569. };
  570. Chapter.prototype.nodeLoaded = function(json, textstatus){
  571. console.log('Chapter :: nodeLoaded '+this.nid+' : json', json);
  572. // remove previous loaded nodes
  573. _$chapter_wrapper.find('.node').remove();
  574. // insert ajax loaded into dom
  575. _$chapter_wrapper.append(json.node);
  576. // record some usefull data
  577. this.$n = $('.node-chapitre', _$chapter_wrapper);
  578. this.$blocks = $('.field-type-text-long', this.$n);
  579. this.$vids_container = $('.field-name-field-partie', this.$n);
  580. this.$vids = $('iframe', this.$vids_container);
  581. // record the current loaded chapter
  582. // this will stop first interface to run
  583. _loaded_chapter = this;
  584. // wait to build correct display of chapter
  585. setTimeout(this.displayNode.bind(this), 100);
  586. };
  587. Chapter.prototype.displayNode = function(){
  588. console.log('Chapter :: displayNode '+this.nid);
  589. // place text blocks
  590. this.texts_pos = shuffleArray([1,2,3]);
  591. this.$blocks
  592. .each(this.placeText.bind(this))
  593. .pep({
  594. allowDragEventPropagation:false,
  595. disableSelect:true,
  596. velocityMultiplier:1
  597. });
  598. // build video player
  599. this.buildVideos();
  600. // show the whole thing
  601. _$chapter_wrapper.addClass('visible');
  602. // this.$vids.eq(this.cur_vid_playing).vimeo('play');
  603. _$body.removeClass('loading');
  604. };
  605. Chapter.prototype.placeText = function(i, e){
  606. // console.log("Chapter :: placeText", e);
  607. switch(this.texts_pos[i]){
  608. case 1: // top right
  609. $(e)
  610. .css({
  611. top:randB(_container.h*0.05-$(e).height(),_container.h*0.15-$(e).height()),
  612. left:randB(_container.w*0.8-$(e).width(),_container.w*0.9-$(e).width())
  613. })
  614. // .pep({debug:true, startPos:{bottom:randB(80,90),right:randB(80,90)}})
  615. .find('.field-label')
  616. .appendTo(e);
  617. break;
  618. case 2: // bottom left
  619. $(e).css({
  620. top:randB(_container.h*0.8,_container.h*0.9),
  621. left:randB(_container.w*0.1,_container.w*0.2)
  622. });
  623. // $(e).pep({debug:true, startPos:{top:randB(80,90),left:randB(10,30)}});
  624. break;
  625. case 3: // bottom right
  626. $(e).css({
  627. top:randB(_container.h*0.8,_container.h*0.9),
  628. left:randB(_container.w*0.7,_container.w*0.9-$(e).width())
  629. });
  630. // $(e).pep({debug:true, startPos:{top:randB(80,90),right:randB(10,30)}});
  631. break;
  632. }
  633. };
  634. Chapter.prototype.buildVideos = function(){
  635. console.log('Chapter :: buildVideos');
  636. this.dimvideo.h = this.$vids_container.height();
  637. // redim each iframe to fit
  638. // add a mask on top of each iframe to avoid bad interaction with vimeo
  639. this.$vids
  640. .after('<div class="mask"></div>')
  641. .each(this.redimVideo.bind(this));
  642. this.$vids_container.css({
  643. width:this.dimvideo.w*1.2,
  644. height:this.dimvideo.h,
  645. marginLeft:(_container.w-this.dimvideo.w*1.2)/2
  646. });
  647. // create the slider with peppermint
  648. this.$slider = $('.field-items', this.$vids_container).Peppermint({
  649. onSlideChange:this.onSlideChange.bind(this)
  650. });
  651. };
  652. Chapter.prototype.redimVideo = function(i,e){
  653. // compute proportional video width ragarding the parent height
  654. this.dimvideo.w = (this.dimvideo.h * parseInt($(e).attr("width")))/parseInt($(e).attr("height"));
  655. // apply thees sizes
  656. $(e)
  657. .css({ width:this.dimvideo.w, height:this.dimvideo.h })
  658. .attr({ width:this.dimvideo.w, height:this.dimvideo.h })
  659. // add some paading to parent for slider display
  660. .parent()
  661. .css({
  662. paddingLeft:this.dimvideo.w*0.15,
  663. paddingright:this.dimvideo.w*0.15
  664. })
  665. .on("click", this.onClickVid.bind(this));
  666. };
  667. Chapter.prototype.onClickVid = function(e){
  668. e.stopPropagation();
  669. e.preventDefault();
  670. console.log('Chapter :: onClickVid '+this.nid, e);
  671. var $vid = $('iframe', e.currentTarget);
  672. $vid.vimeo('paused', function(data){
  673. console.log('paused : ', data);
  674. if(data){
  675. $vid.vimeo('play');
  676. }else{
  677. $vid.vimeo('pause');
  678. }
  679. });
  680. return false;
  681. };
  682. Chapter.prototype.onSlideChange = function(){
  683. console.log('onSlideChange '+this.nid, this.$slider.data('Peppermint').getCurrentPos());
  684. //stop current video playing
  685. this.$vids.eq(this.cur_vid_playing).vimeo('pause');
  686. // start new current video
  687. this.cur_vid_playing = this.$slider.data('Peppermint').getCurrentPos();
  688. this.$vids.eq(this.cur_vid_playing).vimeo('play');
  689. };
  690. Node.initialized = true;
  691. };
  692. this.init();
  693. };//Chapter
  694. /*
  695. __ __________ ____ __________ _____
  696. / / / / ____/ / / __ \/ ____/ __ \/ ___/
  697. / /_/ / __/ / / / /_/ / __/ / /_/ /\__ \
  698. / __ / /___/ /___/ ____/ /___/ _, _/___/ /
  699. /_/ /_/_____/_____/_/ /_____/_/ |_|/____/
  700. */
  701. function randB(min, max){
  702. return Math.random() * (max - min) + min;
  703. };
  704. //+ Jonas Raoni Soares Silva
  705. //@ http://jsfromhell.com/array/shuffle [v1.0]
  706. function shuffleArray(o){ //v1.0
  707. for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
  708. return o;
  709. };
  710. if (!Date.now) {
  711. Date.now = function now() {
  712. return new Date().getTime();
  713. };
  714. }
  715. // function translate3d(x, y, z){
  716. // // return
  717. // };
  718. /*
  719. _ _ __
  720. (_)___ (_) /_
  721. / / __ \/ / __/
  722. / / / / / / /_
  723. /_/_/ /_/_/\__/
  724. */
  725. init();
  726. });
  727. /*
  728. ____ __________ __ ___________________ ___ _ ________ ______ ______________ _ __ __________ ___ __ _________
  729. / __ \/ ____/ __ \/ / / / ____/ ___/_ __/ / | / | / / _/ |/ / |/_ __/ _/ __ \/ | / / / ____/ __ \/ | / |/ / ____/
  730. / /_/ / __/ / / / / / / / __/ \__ \ / / / /| | / |/ // // /|_/ / /| | / / / // / / / |/ / / /_ / /_/ / /| | / /|_/ / __/
  731. / _, _/ /___/ /_/ / /_/ / /___ ___/ // / / ___ |/ /| // // / / / ___ |/ / _/ // /_/ / /| / / __/ / _, _/ ___ |/ / / / /___
  732. /_/ |_/_____/\___\_\____/_____//____//_/ /_/ |_/_/ |_/___/_/ /_/_/ |_/_/ /___/\____/_/ |_/ /_/ /_/ |_/_/ |_/_/ /_/_____/
  733. */
  734. (function() {
  735. var lastTime = 0;
  736. var vendors = ['ms', 'moz', 'webkit', 'o'];
  737. for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
  738. window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
  739. window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
  740. || window[vendors[x]+'CancelRequestAnimationFrame'];
  741. }
  742. if (!window.requestAnimationFrame)
  743. window.requestAnimationFrame = function(callback, element) {
  744. var currTime = new Date().getTime();
  745. var timeToCall = Math.max(0, 16 - (currTime - lastTime));
  746. var id = window.setTimeout(function() { callback(currTime + timeToCall); },
  747. timeToCall);
  748. lastTime = currTime + timeToCall;
  749. return id;
  750. };
  751. if (!window.cancelAnimationFrame)
  752. window.cancelAnimationFrame = function(id) {
  753. clearTimeout(id);
  754. };
  755. }());
  756. /*
  757. ____ ____
  758. / __/_ __/ / / __________________ ___ ____
  759. / /_/ / / / / / / ___/ ___/ ___/ _ \/ _ \/ __ \
  760. / __/ /_/ / / / (__ ) /__/ / / __/ __/ / / /
  761. /_/ \__,_/_/_/ /____/\___/_/ \___/\___/_/ /_/
  762. */
  763. // http://davidwalsh.name/fullscreen
  764. // http://www.sitepoint.com/html5-full-screen-api/
  765. // Find the right method, call on correct element
  766. function launchIntoFullscreen(element) {
  767. if(element.requestFullscreen) {
  768. element.requestFullscreen();
  769. } else if(element.mozRequestFullScreen) {
  770. element.mozRequestFullScreen();
  771. } else if(element.webkitRequestFullscreen) {
  772. element.webkitRequestFullscreen();
  773. } else if(element.msRequestFullscreen) {
  774. element.msRequestFullscreen();
  775. }
  776. }
  777. // Whack fullscreen
  778. function exitFullscreen() {
  779. if(document.exitFullscreen) {
  780. document.exitFullscreen();
  781. } else if(document.mozCancelFullScreen) {
  782. document.mozCancelFullScreen();
  783. } else if(document.webkitExitFullscreen) {
  784. document.webkitExitFullscreen();
  785. }
  786. }
  787. /*
  788. ____ __ __ _____________ _______
  789. / __ \/ / / / / / ____/ _/ | / / ___/
  790. / /_/ / / / / / / / __ / // |/ /\__ \
  791. / ____/ /___/ /_/ / /_/ // // /| /___/ /
  792. /_/ /_____/\____/\____/___/_/ |_//____/
  793. */
  794. // translate3d
  795. (function($) {
  796. $.fn.translate3d = function(opt) {
  797. opt = $.extend({x:0,y:0,z:0}, opt);
  798. var t = "translate3d("+opt.x+"px, "+opt.y+"px,"+opt.z+"px)";
  799. this.css({
  800. "-webkit-transform": t,
  801. "-moz-transform": t,
  802. "-ms-transform": t,
  803. "-o-transform": t,
  804. "transform": t
  805. });
  806. };
  807. })(jQuery);
  808. // https://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/
  809. // (function($) {
  810. // $.fn.drags = function(opt) {
  811. // opt = $.extend({handle:"",cursor:"move"}, opt);
  812. // if(opt.handle === "") {
  813. // var $el = this;
  814. // } else {
  815. // var $el = this.find(opt.handle);
  816. // }
  817. // return $el.css('cursor', opt.cursor).on("mousedown", function(e) {
  818. // if(opt.handle === "") {
  819. // var $drag = $(this).addClass('draggable');
  820. // } else {
  821. // var $drag = $(this).addClass('active-handle').parent().addClass('draggable');
  822. // }
  823. // var z_idx = $drag.css('z-index'),
  824. // drg_h = $drag.outerHeight(),
  825. // drg_w = $drag.outerWidth(),
  826. // pos_y = $drag.offset().top + drg_h - e.pageY,
  827. // pos_x = $drag.offset().left + drg_w - e.pageX;
  828. // $drag.css('z-index', 1000).parents().on("mousemove", function(e) {
  829. // $('.draggable').offset({
  830. // top:e.pageY + pos_y - drg_h,
  831. // left:e.pageX + pos_x - drg_w
  832. // }).on("mouseup", function() {
  833. // $(this).removeClass('draggable').css('z-index', z_idx);
  834. // });
  835. // });
  836. // e.preventDefault(); // disable selection
  837. // }).on("mouseup", function() {
  838. // if(opt.handle === "") {
  839. // $(this).removeClass('draggable');
  840. // } else {
  841. // $(this).removeClass('active-handle').parent().removeClass('draggable');
  842. // }
  843. // });
  844. // }
  845. // })(jQuery);
  846. // remove navbar
  847. // $(document).ready(function() {
  848. // if (navigator.userAgent.match(/Android/i)) {
  849. // window.scrollTo(0,0); // reset in case prev not scrolled
  850. // var nPageH = $(document).height();
  851. // var nViewH = window.outerHeight;
  852. // if (nViewH > nPageH) {
  853. // nViewH -= 250;
  854. // $('BODY').css('height',nViewH + 'px');
  855. // }
  856. // window.scrollTo(0,1);
  857. // }
  858. // });
  859. // OR
  860. // function hideAddressBar(){
  861. // if(document.documentElement.scrollHeight<window.outerHeight/window.devicePixelRatio)
  862. // document.documentElement.style.height=(window.outerHeight/window.devicePixelRatio)+'px';
  863. // setTimeout(window.scrollTo(1,1),0);
  864. // }
  865. // window.addEventListener("load",function(){hideAddressBar();});
  866. // window.addEventListener("orientationchange",function(){hideAddressBar();});
  867. // OR
  868. // function hideAddressBar() {
  869. // if(!window.location.hash) {
  870. // if(document.height < window.outerHeight)
  871. // document.body.style.height = (window.outerHeight + 50) + 'px';
  872. // setTimeout( function(){
  873. // window.scrollTo(0, 1);
  874. // document.body.style.height = 'auto';
  875. // }, 50 );
  876. // }
  877. // }
  878. // window.addEventListener("load",function(){hideAddressBar();});
  879. // window.addEventListener("orientationchange",function(){hideAddressBar();});
  880. // Drupal.behaviors.init_theme = function (context) {
  881. // // Growl-style system messages
  882. // $('#messages-and-help > div.messages:not(.processed)')
  883. // .addClass('processed')
  884. // .each(function() {
  885. // // If a message meets these criteria, we don't autoclose
  886. // // - contains a link
  887. // // - is an error or warning
  888. // // - contains a lenghthy amount of text
  889. // if ($('a', this).size() || $(this).is('.error') || $(this).is('.warning') || $(this).text().length > 100) {
  890. // $(this).prepend("<span class='close'>X</span>");
  891. // $('span.close', this).click(function() {
  892. // $(this).parent().slideUp('fast');
  893. // });
  894. // }
  895. // else {
  896. // // This essentially adds a 3 second pause before hiding the message.
  897. // $(this).animate({opacity:1}, 5000, 'linear', function() {
  898. // $(this).slideUp('fast');
  899. // });
  900. // }
  901. // });
  902. // };