jee.js 31 KB

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