/* _ _ |_|___ _ _ ___ ___ ___ ___| |_ ___ ___ ___ ___ ___ ___ ___ | | -_| | | | -_|_ -| | -_| _| | -_| | . | .'| . | -_|_ -| _| |___|___|_|_|___|___| |___|_| |___|_|_|_ |__,|_ |___|___| |___| |___| |___| Bachir Soussi Chiadmi 2015 */ jQuery(document).ready(function($) { console.log('Hello Jee'); var _debug = true, _avgDelay = 1, _lastDraw = new Date, _fps, _$nav_cursor; var _$body = $('body'), _$header = $("#header"), _$chapitres = $('.node-chapitre', '#main'), _chapitres_len = _$chapitres.length, _chapters = [], _$container = $('#main'), _container = { w:_$container.width(), h:_$container.height() }, _center = {x:_container.w/2,y:_container.h/2}, _nav_pos = {x:0, y:0}, _mouse_down_pos = {x:0,y:0}, _prev_mouse_pos = {x:0,y:0}, _fps = 1000/12, _dragging = false, _timeout_dragging; var _$chapter_wrapper = $('
').attr('id', 'chapter-wrapper').appendTo(_$container), _loaded_chapter = false; var _bubbles = new Array(), _stars = new Array(); function init(){ if(_debug) initDebug(); initChapters(); launchNav(); // FULL SCREEN var $fullscreenBtn = $('
enter
').attr('id','fullscreen-btn').appendTo("#root"); $fullscreenBtn.on('click', onFullScreen); // create bubbles for (var i = 2; i > 0; i--) { _bubbles.push($('
').addClass('bubble bubble-'+i).prependTo(_$container)); }; // create stars for (var i = 20; i > 0; i--) { _stars.push( $('
') .addClass('star star-'+i) .css({ left:randB(-400, _container.w+400), top:randB(-400, _container.h+400) }) .prependTo(_$container) ); }; }; function initDebug(){ $('

').attr('id', 'fps').appendTo(_$container); _fps = document.getElementById('fps'); requestAnimationFrame(displayFps); _$nav_cursor = $('

').appendTo(_$container); moveDebugCursor(); }; function displayFps(){ requestAnimationFrame(displayFps); var now = new Date; var delay = now - _lastDraw; _avgDelay += (delay - _avgDelay) / 10; _lastDraw = now; _fps.innerHTML = (1000/_avgDelay).toFixed(1) + " fps"; }; function moveDebugCursor(){ _$nav_cursor.css({ left:_nav_pos.x+_center.x+"px", top:_nav_pos.y+_center.y+"px" }); }; function initChapters(){ // Place each chapters on the ellipse contained on the screen var base_a = Math.random() *360; _$chapitres.each(function(i, e) { // Lets create the chapter object and place him self _chapters.push(new Chapter(i, e, base_a)); }); }; function launchNav(){ $(document) /* ____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ | \| __| __| | |_ _| | _ | | __| | | __| | |_ _| __| | | | __|__ | -| | | | | | __| | __| | | __| | | | | | |__ | |____/|_____|_____|__|__| |_| |_____|__| |_____|\___/|_____|_|___| |_| |_____| */ .bind('mousedown', function(e){ console.log('document mousedown'); clearTimeout(_timeout_dragging); if(_loaded_chapter) return false; // set initial cursor pos _mouse_down_pos.x = e.clientX; _mouse_down_pos.y = e.clientY; updateNavPos(e.clientX, e.clientY, true); $(this).bind('mousemove', function(e){ console.log('document mousemove'); updateNavPos(e.clientX, e.clientY, false); }); // activate dragging if already activated if(!_dragging){ _dragging = true; startMoveNav(); } }) .bind('mouseup', function(e){ console.log('document mouseup'); if(_loaded_chapter) return false; stopMoveNav(); $(this).unbind('mousemove'); // close all preview if(Math.abs(e.clientX - _mouse_down_pos.x) < 2 && Math.abs(e.clientY - _mouse_down_pos.y) < 2) for (var i = _chapitres_len - 1; i >= 0; i--) _chapters[i].closePreview().unMitigate(); }) /* _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ _____ |_ _| | | | | | | | __| | | __| | |_ _| __| | | | | | | | --| | | __| | | __| | | | | | |__ | |_| |_____|_____|_____|__|__| |_____|\___/|_____|_|___| |_| |_____| */ .bind('document touchstart', function(e){ console.log('touchstart'); clearTimeout(_timeout_dragging); // set initial pos updateNavPos(e.originalEvent.touches[0].clientX, e.originalEvent.touches[0].clientY, true); // activate dragging if already activated if(!_dragging){ _dragging = true; startMoveNav(); } }) .bind('touchmove', function(e){ console.log('document touchmove'); updateNavPos(e.originalEvent.touches[0].clientX, e.originalEvent.touches[0].clientY, false); }) .bind('touchend', function(e){ console.log("document touchend"); stopMoveNav(); }); }; function updateNavPos(x,y,init){ if(!init){ _nav_pos.x += x - _prev_mouse_pos.x; _nav_pos.y += y - _prev_mouse_pos.y; // constrain nav pos on container _nav_pos.x = _nav_pos.x < -_center.x*2 ? -_center.x*2 : _nav_pos.x > _center.x*2 ? _center.x*2 : _nav_pos.x; _nav_pos.y = _nav_pos.y < -_center.y*2 ? -_center.y*2 : _nav_pos.y > _center.y*2 ? _center.y*2 : _nav_pos.y; } _prev_mouse_pos.x = x; _prev_mouse_pos.y = y; // debuging cursor if(_debug) moveDebugCursor(); }; function startMoveNav(){ window.requestAnimationFrame(moveNav); }; function moveNav(){ // console.log("moveNav"); if(!_dragging) return; window.requestAnimationFrame(moveNav); // move chapters for (var i = _chapitres_len - 1; i >= 0; i--) _chapters[i].move(); // move header _$header.css({ transform:"translate3d("+(_nav_pos.x)*0.2+"px, "+(_nav_pos.y)*0.2+"px,0)" }); // bubbles and stars dont move so smoothly on tablette ... // should keep it only on desktop // move bubbles // for (var i = _bubbles.length - 1; i >= 0; i--) { // _bubbles[i].css({ // transform:"translate3d("+(_nav_pos.x)*0.4+"px, "+(_nav_pos.y)*0.4+"px,0)" // }); // }; // move stars // for (var i = _stars.length - 1; i >= 0; i--) { // _stars[i].css({ // transform:"translate3d("+(_nav_pos.x)*-0.3+"px, "+(_nav_pos.y)*-0.3+"px,0)" // }); // }; }; function stopMoveNav(){ console.log('stopMoveNav'); clearTimeout(_timeout_dragging); _timeout_dragging = setTimeout(function(){ console.log("dragging stoped"); _dragging = false; },3000); }; function moveToChapter(chapter){ // fake a mousdown by providing first pos as current pos _prev_mouse_pos.x = _nav_pos.x; _prev_mouse_pos.y = _nav_pos.y; // calculate the second pos of faked mousemove var xl = _center.x - chapter.pos.x - chapter.geom.w/2; var yl = 100 - chapter.pos.y; updateNavPos(xl, yl, false); startMoveNav(); stopMoveNav(); }; function onFullScreen(e){ launchIntoFullscreen(document.getElementById("root")); if(_loaded_chapter) setTimeout(_loaded_chapter.buildVideos(), 100); }; /* ________ __ / ____/ /_ ____ _____ / /____ _____ / / / __ \/ __ `/ __ \/ __/ _ \/ ___/ / /___/ / / / /_/ / /_/ / /_/ __/ / \____/_/ /_/\__,_/ .___/\__/\___/_/ /_/ */ function Chapter(i, e, base_a){ // $e.obj = this; this.i = i; this.e = e; this.$e = $(e); this.nid = this.$e.attr("id").match(/^node-(\d+)/)[1]; this.geom = { base_a:base_a, a:0, r:0, w:this.$e.outerWidth(true), h:this.$e.outerHeight(true) } this.pos = {x:0,y:0}; this.trans = {x:0, y:0,z:0}; this.ease = randB(0.05, 0.3); //preview this.is_previewed = false; //mitigate this.is_mitigated = false; //parties this.$parties = $('.field-name-field-partie', e); this.parts_pos = {xs:new Array(), ys:new Array()}; this.lines = new Array(); this.linesAnimeStartTime = 0, this.linesAnimeDuration = 2000; // milli sec // chapter this.$n = false; this.$blocks = false; this.$vids = false; this.texts_pos = shuffleArray([1,2,3]); this.dimvideo = {w:0, h:0}; // prototypes if (typeof Chapter.initialized == "undefined") { Chapter.prototype.init = function(){ this.setInitPos(); this.drawLines(); this.setEvents(); }; Chapter.prototype.setInitPos = function(){ // distribute elements arround the center this.geom.a = (360/_chapitres_len*this.i+this.geom.base_a)*Math.PI/180; // console.log("Chapter :: setInitPos", this.$e); this.geom.c = Math.cos(this.geom.a); this.geom.s = Math.sin(this.geom.a); this.geom.abs_c = Math.abs(this.geom.c); this.geom.abs_s = Math.abs(this.geom.s); if (this.geom.abs_c * _container.h > this.geom.abs_s * _container.w) { // It crosses left or right side this.geom.r = (_center.x / this.geom.abs_c)*0.5; }else { // Top or bottom side this.geom.r = (_center.y / this.geom.abs_s)*0.5; } // change randomly radius if(this.i%2){ this.geom.r = randB(this.geom.r*2, this.geom.r*3); }else{ this.geom.r = randB(this.geom.r, this.geom.r*2); } this.pos.x = Math.round(_center.x+this.geom.r * this.geom.c) - this.geom.w/2; this.pos.y = Math.round(_center.y+this.geom.r * -this.geom.s) - this.geom.h/2; console.log('this', this); this.$e.css({ left:this.pos.x, top:this.pos.y }); };// setIniPos() Chapter.prototype.setEvents = function(){ //http://technify.me/user-experience/javascript/jquery/trigger-custom-events-with-jquery/ // click to preview chapter $('h2.node-title, .field-name-field-partie:first>.field-name-field-vignette', this.$e) .on('click', this, function(e){ // e.stopImmediatePropagation(); e.stopPropagation(); e.preventDefault(); e.data.preview(e); return false; }); $('.links a', this.$e) .on('click', this, function(e){ e.stopPropagation(); e.preventDefault(); e.data.loadNode(); return false; }); }; Chapter.prototype.move = function(){ this.trans.x += (_nav_pos.x - this.trans.x)*this.ease; this.trans.y += (_nav_pos.y - this.trans.y)*this.ease; // this.trans.z = Math.floor(Math.sqrt( // Math.pow( // _center.x-(this.pos.x+this.trans.x) // ,2 // ) // + // Math.pow( // _center.y-(this.pos.y+this.trans.y) // ,2 // ) // )); // if(this.i === 0) // console.log(this.i+" this.trans.z", this.trans.z); this.$e.css({ transform:'translate3d('+this.trans.x+'px,'+this.trans.y+'px,0)' // scale:this.trans.z }); }; Chapter.prototype.preview = function(){ // don't relaunch preview more that one time if(this.is_previewed) return; console.log('preview', this.i); this.unMitigate(); this.is_previewed = true; // close other chapters for (var i = _chapitres_len - 1; i >= 0; i--) if(i !== this.i) _chapters[i].closePreview().mitigate(); this.displayPreview(); moveToChapter(this); }; Chapter.prototype.displayPreview = function(e){ // define randomly position of parties this.resetPartsPos(); // apply new position to parties var that = this; this.$parties.each(function(i, e) { setTimeout( (function(i, e, xs, ys){ return function(){ $(e) .css({ transform:"translate3d("+xs[i]+"px,"+ys[i]+"px,0)", }); } }(i, e, that.parts_pos.xs, that.parts_pos.ys)), 10); }); // each $parties this.$e.addClass('previewed'); requestAnimationFrame(this.animeLines.bind(this)); }; Chapter.prototype.resetPartsPos = function(){ this.parts_pos = {xs:new Array(), ys:new Array()}; for (var i = 0; i < 3; i++) { switch(i){ case 0: this.parts_pos.xs.push(randB(-30,30)); this.parts_pos.ys.push(randB(90,110)); break; case 1: this.parts_pos.xs.push(randB(180,280)); this.parts_pos.ys.push(randB(250,350)); break; case 2: this.parts_pos.xs.push(randB(-280,-180)); this.parts_pos.ys.push(randB(430,530)); break; } }; this.parts_pos.xs = shuffleArray(this.parts_pos.xs); this.parts_pos.ys = shuffleArray(this.parts_pos.ys); }; Chapter.prototype.closePreview = function(){ if(!this.is_previewed) return this; this.$e.removeClass('previewed') .find('.field-name-field-partie') .css({transform:"none"}); requestAnimationFrame(this.animeLines.bind(this)); this.is_previewed = false; return this; }; Chapter.prototype.mitigate = function(){ if(this.is_mitigated) return this; this.$e.addClass('mitigated'); return this; }; Chapter.prototype.unMitigate = function(){ if(this.is_mitigated) return this; this.$e.removeClass('mitigated'); return this; }; Chapter.prototype.drawLines = function(){ for (var i = 0; i < 2; i++) { this.lines.push({ $line:$("
").addClass('line', 'line-'+i).prependTo(this.$parties[i]) }); }; }; Chapter.prototype.animeLines = function(timestamp){ // console.log("anime line "+this.nid); // get the time on first anime launch if(this.linesAnimeStartTime === 0) this.linesAnimeStartTime = timestamp; // limit the animation time if(timestamp - this.linesAnimeStartTime < this.linesAnimeDuration){ requestAnimationFrame(this.animeLines.bind(this)); }else{ this.linesAnimeStartTime = 0; } // get the lines length var l, a, pos1, pos2; for (var i = 0; i < this.lines.length; i++) { pos1 = this.$parties.eq(i).position(); pos2 = this.$parties.eq(i+1).position(); l = Math.sqrt( Math.pow( pos2.left - pos1.left ,2 ) + Math.pow( pos2.top - pos1.top ,2 ) ); // get the rotation a = 180 / 3.14 * Math.acos((pos2.top - pos1.top) / l); if(pos2.left > pos1.left) a *= -1; // console.log("a = "+a); this.lines[i].$line.css({ 'height':l, transform:"rotate3d(0,0,1,"+a+"deg)" }); }; }; Chapter.prototype.loadNode = function(e){ // console.log("Chapter :: open : nid", this.nid); $.getJSON( '/jee/chapter/'+this.nid, {}, this.nodeLoaded.bind(this) ); _$body.addClass('chapter-displayed'); }; Chapter.prototype.nodeLoaded = function(json, textstatus){ console.log('Chapter :: nodeLoaded '+this.nid+' : json', json); // insert ajax loaded into dom _$chapter_wrapper.html(json.node); // record some usefull data this.$n = $('.node-chapitre', _$chapter_wrapper); this.$blocks = $('.field-type-text-long', this.$n); this.$vids = $('.field-name-field-partie', this.$n); // record the current loaded chapter // this will stop first interface to run _loaded_chapter = this; // wait to build correct display of chapter setTimeout(this.displayNode.bind(this), 100); }; Chapter.prototype.displayNode = function(){ console.log('Chapter :: displayNode '+this.nid); // place text blocks this.texts_pos = shuffleArray([1,2,3]); this.$blocks .each(this.placeText.bind(this)) .pep({ allowDragEventPropagation:false, disableSelect:true, velocityMultiplier:1 }); // build video player this.buildVideos(); $('.node-title', this.$n).pep(); // show the whole thing _$chapter_wrapper.addClass('visible'); }; Chapter.prototype.placeText = function(i, e){ // console.log("Chapter :: placeText", e); switch(this.texts_pos[i]){ case 1: // top right $(e) .css({ top:randB(_container.h*0.05-$(e).height(),_container.h*0.15-$(e).height()), left:randB(_container.w*0.8-$(e).width(),_container.w*0.9-$(e).width()) }) // .pep({debug:true, startPos:{bottom:randB(80,90),right:randB(80,90)}}) .find('.field-label') .appendTo(e); break; case 2: // bottom left $(e).css({ top:randB(_container.h*0.8,_container.h*0.9), left:randB(_container.w*0.1,_container.w*0.2) }); // $(e).pep({debug:true, startPos:{top:randB(80,90),left:randB(10,30)}}); break; case 3: // bottom right $(e).css({ top:randB(_container.h*0.8,_container.h*0.9), left:randB(_container.w*0.7,_container.w*0.9-$(e).width()) }); // $(e).pep({debug:true, startPos:{top:randB(80,90),right:randB(10,30)}}); break; } }; Chapter.prototype.buildVideos = function(){ console.log('Chapter :: buildVideos'); this.dimvideo.h = this.$vids.height(); // redim each iframe to fit // add a mask on top of each iframe to avoid bad interaction with vimeo $('iframe', this.$vids) .each(this.redimVideo.bind(this)) .after('
'); this.$vids.css({ width:this.dimvideo.w*1.3, height:this.dimvideo.h, marginLeft:(_container.w-this.dimvideo.w*1.3)/2 }); // create the slider with peppermint $('.field-items', this.$vids).Peppermint(); }; Chapter.prototype.redimVideo = function(i,e){ // compute proportional video width ragarding the parent height this.dimvideo.w = (this.dimvideo.h * parseInt($(e).attr("width")))/parseInt($(e).attr("height")); // apply thees sizes $(e) .css({ width:this.dimvideo.w, height:this.dimvideo.h }) .attr({ width:this.dimvideo.w, height:this.dimvideo.h }) // add some paading to parent for slider display .parent().css({ paddingLeft:this.dimvideo.w*0.15, paddingright:this.dimvideo.w*0.15 }); }; Node.initialized = true; }; this.init(); };//Chapter /* __ __________ ____ __________ _____ / / / / ____/ / / __ \/ ____/ __ \/ ___/ / /_/ / __/ / / / /_/ / __/ / /_/ /\__ \ / __ / /___/ /___/ ____/ /___/ _, _/___/ / /_/ /_/_____/_____/_/ /_____/_/ |_|/____/ */ function randB(min, max){ return Math.random() * (max - min) + min; }; //+ Jonas Raoni Soares Silva //@ http://jsfromhell.com/array/shuffle [v1.0] function shuffleArray(o){ //v1.0 for(var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); return o; }; if (!Date.now) { Date.now = function now() { return new Date().getTime(); }; } function translate3d(x, y, z){ // return }; /* _ _ __ (_)___ (_) /_ / / __ \/ / __/ / / / / / / /_ /_/_/ /_/_/\__/ */ init(); }); /* ____ __ __ _____________ _______ / __ \/ / / / / / ____/ _/ | / / ___/ / /_/ / / / / / / / __ / // |/ /\__ \ / ____/ /___/ /_/ / /_/ // // /| /___/ / /_/ /_____/\____/\____/___/_/ |_//____/ */ // https://css-tricks.com/snippets/jquery/draggable-without-jquery-ui/ // (function($) { // $.fn.drags = function(opt) { // opt = $.extend({handle:"",cursor:"move"}, opt); // if(opt.handle === "") { // var $el = this; // } else { // var $el = this.find(opt.handle); // } // return $el.css('cursor', opt.cursor).on("mousedown", function(e) { // if(opt.handle === "") { // var $drag = $(this).addClass('draggable'); // } else { // var $drag = $(this).addClass('active-handle').parent().addClass('draggable'); // } // var z_idx = $drag.css('z-index'), // drg_h = $drag.outerHeight(), // drg_w = $drag.outerWidth(), // pos_y = $drag.offset().top + drg_h - e.pageY, // pos_x = $drag.offset().left + drg_w - e.pageX; // $drag.css('z-index', 1000).parents().on("mousemove", function(e) { // $('.draggable').offset({ // top:e.pageY + pos_y - drg_h, // left:e.pageX + pos_x - drg_w // }).on("mouseup", function() { // $(this).removeClass('draggable').css('z-index', z_idx); // }); // }); // e.preventDefault(); // disable selection // }).on("mouseup", function() { // if(opt.handle === "") { // $(this).removeClass('draggable'); // } else { // $(this).removeClass('active-handle').parent().removeClass('draggable'); // } // }); // } // })(jQuery); /* ____ __________ __ ___________________ ___ _ ________ ______ ______________ _ __ __________ ___ __ _________ / __ \/ ____/ __ \/ / / / ____/ ___/_ __/ / | / | / / _/ |/ / |/_ __/ _/ __ \/ | / / / ____/ __ \/ | / |/ / ____/ / /_/ / __/ / / / / / / / __/ \__ \ / / / /| | / |/ // // /|_/ / /| | / / / // / / / |/ / / /_ / /_/ / /| | / /|_/ / __/ / _, _/ /___/ /_/ / /_/ / /___ ___/ // / / ___ |/ /| // // / / / ___ |/ / _/ // /_/ / /| / / __/ / _, _/ ___ |/ / / / /___ /_/ |_/_____/\___\_\____/_____//____//_/ /_/ |_/_/ |_/___/_/ /_/_/ |_/_/ /___/\____/_/ |_/ /_/ /_/ |_/_/ |_/_/ /_/_____/ */ (function() { var lastTime = 0; var vendors = ['ms', 'moz', 'webkit', 'o']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame']; } if (!window.requestAnimationFrame) window.requestAnimationFrame = function(callback, element) { var currTime = new Date().getTime(); var timeToCall = Math.max(0, 16 - (currTime - lastTime)); var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall); lastTime = currTime + timeToCall; return id; }; if (!window.cancelAnimationFrame) window.cancelAnimationFrame = function(id) { clearTimeout(id); }; }()); /* ____ ____ / __/_ __/ / / __________________ ___ ____ / /_/ / / / / / / ___/ ___/ ___/ _ \/ _ \/ __ \ / __/ /_/ / / / (__ ) /__/ / / __/ __/ / / / /_/ \__,_/_/_/ /____/\___/_/ \___/\___/_/ /_/ */ // http://davidwalsh.name/fullscreen // http://www.sitepoint.com/html5-full-screen-api/ // Find the right method, call on correct element function launchIntoFullscreen(element) { if(element.requestFullscreen) { element.requestFullscreen(); } else if(element.mozRequestFullScreen) { element.mozRequestFullScreen(); } else if(element.webkitRequestFullscreen) { element.webkitRequestFullscreen(); } else if(element.msRequestFullscreen) { element.msRequestFullscreen(); } } // remove navbar // $(document).ready(function() { // if (navigator.userAgent.match(/Android/i)) { // window.scrollTo(0,0); // reset in case prev not scrolled // var nPageH = $(document).height(); // var nViewH = window.outerHeight; // if (nViewH > nPageH) { // nViewH -= 250; // $('BODY').css('height',nViewH + 'px'); // } // window.scrollTo(0,1); // } // }); // OR // function hideAddressBar(){ // if(document.documentElement.scrollHeight div.messages:not(.processed)') // .addClass('processed') // .each(function() { // // If a message meets these criteria, we don't autoclose // // - contains a link // // - is an error or warning // // - contains a lenghthy amount of text // if ($('a', this).size() || $(this).is('.error') || $(this).is('.warning') || $(this).text().length > 100) { // $(this).prepend("X"); // $('span.close', this).click(function() { // $(this).parent().slideUp('fast'); // }); // } // else { // // This essentially adds a 3 second pause before hiding the message. // $(this).animate({opacity:1}, 5000, 'linear', function() { // $(this).slideUp('fast'); // }); // } // }); // };