jee.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. //
  2. // by Bachir Soussi Chiadmi
  3. // 2015
  4. //
  5. jQuery(document).ready(function($) {
  6. console.log('Hello Jee');
  7. var _$header = $("#header"),
  8. _$chapitres = $('.node-chapitre', '#main'),
  9. _chapitres_len = _$chapitres.length,
  10. _chapters = [],
  11. _$container = $('#main'),
  12. _container = {
  13. w:_$container.width(),
  14. h:_$container.height()
  15. },
  16. _center = {x:_container.w/2,y:_container.h/2},
  17. _nav_pos = {x:0, y:0},
  18. _nav_timer,
  19. _last_client = {x:0,y:0},
  20. _fps = 1000/12,
  21. _dragging = false;
  22. function init(){
  23. initChapters();
  24. launchNav();
  25. };
  26. function initChapters(){
  27. // Place each chapters on the ellipse contained on the screen
  28. var base_a = Math.random() *360;
  29. _$chapitres.each(function(i, e) {
  30. // Lets create the chapter object and place him self
  31. _chapters.push(new Chapter(i, $(e), base_a));
  32. });
  33. };
  34. function launchNav(){
  35. _$container
  36. // DESKTOP EVENTS
  37. .bind('mousedown', function(e){
  38. if(_dragging) return false;
  39. _dragging = true;
  40. console.log('mousedown');
  41. _last_client.x=e.clientX;
  42. _last_client.y=e.clientY;
  43. _$chapitres.each(function(i, e) {
  44. $(e).css({"transitionDuration":randB(0.1, 0.3)+"s"});
  45. });
  46. _nav_timer = setInterval(moveNav, _fps);
  47. $(this).bind('mousemove', function(e){
  48. console.log('mousemove');
  49. _nav_pos.x += e.clientX - _last_client.x;
  50. _nav_pos.y += e.clientY - _last_client.y;
  51. _last_client.x = e.clientX;
  52. _last_client.y = e.clientY;
  53. // moveNav();
  54. });
  55. })
  56. .bind('mouseup', function(e){
  57. console.log('mouseup');
  58. _dragging = false;
  59. // clearInterval(_nav_timer);
  60. $(this).unbind('mousemove');
  61. })
  62. //
  63. // TOUCH EVENTS - - - - - - - - - - - - - -
  64. //
  65. .bind('touchstart', function(e){
  66. if(_dragging) return false;
  67. _dragging = true;
  68. console.log('touchstart');
  69. _last_client.x = e.originalEvent.touches[0].clientX;
  70. _last_client.y = e.originalEvent.touches[0].clientY;
  71. _$chapitres.each(function(i, e) {
  72. $(e).css({"transitionDuration":randB(0.1, 0.3)+"s"});
  73. });
  74. _nav_timer = setInterval(moveNav, _fps);
  75. })
  76. .bind('touchmove', function(e){
  77. console.log('touchmove');
  78. _nav_pos.x += e.originalEvent.touches[0].clientX - _last_client.x;
  79. _nav_pos.y += e.originalEvent.touches[0].clientY - _last_client.y;
  80. _last_client.x = e.originalEvent.touches[0].clientX;
  81. _last_client.y = e.originalEvent.touches[0].clientY;
  82. // moveNav();
  83. })
  84. .bind('touchend', function(e){
  85. console.log("touchend");
  86. _dragging = false;
  87. // clearInterval(_nav_timer);
  88. });
  89. // click to preview chapter
  90. // $('h2.node-title, .field-name-field-partie:first>.field-name-field-vignette', _$chapitres).bind('click', previewChapter);
  91. // $('.links a', _$chapitres).on('click', openChapter);
  92. };
  93. function moveNav(){
  94. // console.log("moveNav");
  95. // move chapters
  96. for (var i = _chapitres_len - 1; i >= 0; i--) {
  97. _chapters[i].move();
  98. };
  99. // move header
  100. _$header.stop(true, false).css({
  101. translate:[_nav_pos.x*0.2, _nav_pos.y*0.2]
  102. });
  103. };
  104. /*
  105. * Chapter
  106. *
  107. */
  108. function Chapter(i, $e, base_a){
  109. $e.obj = this;
  110. this.i = i;
  111. this.$e = $e;
  112. this.nid = $e.attr("id").match(/^node-(\d+)/)[1];
  113. this.geom = {
  114. base_a:base_a,
  115. a:0,
  116. r:0
  117. }
  118. this.pos = {x:0,y:0};
  119. this.translation = {x:0, y:0};
  120. //parties
  121. this.$parties = $('.field-name-field-partie', $e);
  122. this.lines = new Array();
  123. this.linesAnimeInterval = null;
  124. this.linesAnimeCounter = 0;
  125. this.linesAnimeTime = 5; // sec
  126. // prototypes
  127. if (typeof Chapter.initialized == "undefined") {
  128. Chapter.prototype.init = function(){
  129. // var _this = this;
  130. // this.$parties.each(function(i, e){
  131. // _this.partie.push({$partie:$(this)});
  132. // });
  133. this.setInitPos();
  134. this.drawLines();
  135. this.setEvents();
  136. };
  137. Chapter.prototype.setInitPos = function(){
  138. // distribute elements arround the center
  139. this.geom.a = (360/_chapitres_len*this.i+this.geom.base_a)*Math.PI/180;
  140. // console.log("Chapter :: setInitPos", this.$e);
  141. this.geom.c = Math.cos(this.geom.a);
  142. this.geom.s = Math.sin(this.geom.a);
  143. this.geom.abs_c = Math.abs(this.geom.c);
  144. this.geom.abs_s = Math.abs(this.geom.s);
  145. if (this.geom.abs_c * _container.h > this.geom.abs_s * _container.w) {
  146. // It crosses left or right side
  147. this.geom.r = ((_container.w/2) / this.geom.abs_c)*0.5;
  148. }else {
  149. // Top or bottom side
  150. this.geom.r = ((_container.h/2) / this.geom.abs_s)*0.5;
  151. }
  152. // change randomly radius
  153. this.geom.r = randB(this.geom.r, this.geom.r*2);
  154. this.pos.x = Math.round(_center.x+this.geom.r * this.geom.c) - this.$e.outerWidth(true)/2;
  155. this.pos.y = Math.round(_center.y+this.geom.r * -this.geom.s) - this.$e.outerHeight(true)/2;
  156. console.log('this', this);
  157. this.$e.css({
  158. left:this.pos.x,
  159. top:this.pos.y
  160. });
  161. };// setIniPos()
  162. Chapter.prototype.setEvents = function(){
  163. //http://technify.me/user-experience/javascript/jquery/trigger-custom-events-with-jquery/
  164. // click to preview chapter
  165. $('h2.node-title, .field-name-field-partie:first>.field-name-field-vignette', this.$e)
  166. .on('click', this, function(e){
  167. e.stopPropagation();
  168. e.preventDefault();
  169. e.data.preview(e);
  170. return false;
  171. });
  172. $('.links a', this.$e)
  173. .on('click', this, function(e){
  174. e.stopPropagation();
  175. e.preventDefault();
  176. e.data.loadNode();
  177. return false;
  178. });
  179. };
  180. Chapter.prototype.move = function(){
  181. this.$e.css({ //.stop(true, false)
  182. translate:[_nav_pos.x, _nav_pos.y]
  183. });
  184. // $(e).transition({translate:[_nav_pos.x, _nav_pos.y]}, 200, 'out');
  185. };
  186. Chapter.prototype.preview = function(e){
  187. console.log('preview', this.i);
  188. for (var i = _chapitres_len - 1; i >= 0; i--) {
  189. if(i !== this.i)
  190. _chapters[i].closePreview();
  191. };
  192. var px, py;
  193. this.$parties.each(function(i, e) {
  194. switch(i){
  195. case 0:
  196. px=randB(-40, 40); py=randB(40, 60);
  197. break;
  198. case 1:
  199. px=randB(100, 200); py=randB(120,220);
  200. break;
  201. case 2:
  202. px=randB(-200, -100); py=randB(250,320);
  203. break;
  204. }
  205. setTimeout(
  206. (function(e, px, py){
  207. return function(){
  208. $(e)
  209. .css({
  210. translate:[px, py],
  211. // opacity:1
  212. });
  213. }
  214. }(e, px, py)),
  215. 10);
  216. }); // each $parties
  217. this.$e.addClass('previewed');
  218. this.animeLines();
  219. };
  220. Chapter.prototype.closePreview = function(){
  221. this.$e.removeClass('previewed')
  222. .find('.field-name-field-partie')
  223. .css({transform:"none"});
  224. };
  225. Chapter.prototype.drawLines = function(){
  226. for (var i = 0; i < 2; i++) {
  227. this.lines.push({
  228. $line:$("<div>").addClass('line', 'line-'+i).prependTo(this.$parties[i])
  229. });
  230. };
  231. };
  232. Chapter.prototype.animeLines = function(){
  233. this.linesAnimeCounter = 0;
  234. this.linesAnimeInterval = setInterval(
  235. (function(_this){
  236. return function(){
  237. // console.log("partie pos : ", _this.$parties.eq(2).position());
  238. // get the lines length
  239. var l, a, pos1, pos2;
  240. for (var i = 0; i < _this.lines.length; i++) {
  241. pos1 = _this.$parties.eq(i).position();
  242. pos2 = _this.$parties.eq(i+1).position();
  243. l = Math.sqrt(
  244. Math.pow(
  245. pos2.left - pos1.left
  246. ,2
  247. )
  248. +
  249. Math.pow(
  250. pos2.top - pos1.top
  251. ,2
  252. )
  253. );
  254. // get the rotation
  255. a = 180 / 3.14 * Math.acos((pos2.top - pos1.top) / l);
  256. if(pos2.left > pos1.left)
  257. a *= -1;
  258. // console.log("a = "+a);
  259. _this.lines[i].$line.css({
  260. 'height':l,
  261. rotate:a+"deg"
  262. });
  263. };
  264. // limit the naimation time
  265. _this.linesAnimeCounter ++;
  266. if(_this.linesAnimeCounter > (1000/_fps)*_this.linesAnimeTime)
  267. clearInterval(_this.linesAnimeInterval);
  268. };
  269. }(this)),
  270. _fps);
  271. };
  272. Chapter.prototype.loadNode = function(e){
  273. // console.log("Chapter :: open : nid", this.nid);
  274. $.getJSON(
  275. '/jee/chapter/'+this.nid,
  276. {},
  277. this.displayNode
  278. );
  279. };
  280. Chapter.prototype.displayNode = function(json, textstatus){
  281. console.log('Chapter :: displayNode : json', json);
  282. };
  283. Node.initialized = true;
  284. }
  285. this.init();
  286. };//Chapter
  287. /* HELPERS */
  288. function randB(min, max){
  289. return Math.random() * (max - min) + min;
  290. }
  291. init();
  292. });
  293. // Drupal.behaviors.init_theme = function (context) {
  294. // // Growl-style system messages
  295. // $('#messages-and-help > div.messages:not(.processed)')
  296. // .addClass('processed')
  297. // .each(function() {
  298. // // If a message meets these criteria, we don't autoclose
  299. // // - contains a link
  300. // // - is an error or warning
  301. // // - contains a lenghthy amount of text
  302. // if ($('a', this).size() || $(this).is('.error') || $(this).is('.warning') || $(this).text().length > 100) {
  303. // $(this).prepend("<span class='close'>X</span>");
  304. // $('span.close', this).click(function() {
  305. // $(this).parent().slideUp('fast');
  306. // });
  307. // }
  308. // else {
  309. // // This essentially adds a 3 second pause before hiding the message.
  310. // $(this).animate({opacity:1}, 5000, 'linear', function() {
  311. // $(this).slideUp('fast');
  312. // });
  313. // }
  314. // });
  315. // };