jee.js 32 KB

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