jee.js 34 KB

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