Vuejs 2.5 vertical page animation 2

by jpeter06

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/2.1.0/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="main">
  <p-menu></p-menu>
  <div id="pageCont">
    <transition :name="transitionName" >
      <keep-alive :max="2">
      <component v-bind:is="page"></component>
      </keep-alive>
    </transition>
  </div>
</div>

<template id="pMenu">
  <div class="menu" v-bind:class="{ active: isActive }">
    <div id="cabecera">TITULO</div>
    <ul>
      <li  v-bind:class="[page==item ?'focused':'']" v-for="item  in items" v-on:click="click(item)">
      {{item}}
      </li>
    </ul>
  </div>
</template>

<!-- PAGES -->
<template id="page2">
  <div class="page page2"  style="background:#eeeeee">
   Page2
   <innertext2>sd</innertext2>
   <innertext/>
   <innertext2/>
  </div>
</template>
 
<template id="page1">
  <div class="page page1"  style="background:#eeeeee">
   Page1
   <innertext2> </innertext2>
   <innertext> </innertext>
   <innertext2> </innertext2>
   <innertext> </innertext>
  </div>
</template>
 
<template id="page3">
  <div class="page page3" style="background:#eeeeee">
  Page3
  <innertext/>
  </div>
</template>

<template id="page4">
  <div class="page page4" style="background:#eeeeee">
  Page4
  <innertext/>
  </div>
</template>



<template id="innertext">
  <div style="text-align: justify;">
  Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr,  sed diam...

CSS

html, body ,#main
{
    height: 100%;
    width: 100%;
    margin: 0px;
    padding: 0px;
    overflow: hidden;
    background:#eee;
    font-family:Arial;
}

#main{
  display:flex; flex-direction:column;
}
#cabecera{  flex-grow:0;height:40px;text-align:center; 
            color:#555; font-size:30px; ;
           /* box-shadow: 1px 6px 10px 0px rgba(0,0,0,0.44);*/ }
#pageCont{flex-grow:1;position:relative;border: 10px solid transparent;}
.page{
   width:100%;height:100%;
   position: absolute;top:0px;left:0px;
   /*box-shadow: 1px 6px 13px 0px rgba(0,0,0,0.44);*/
   box-sizing: border-box;
   display: block;
   padding:12px;
   text-align:center;
   /*transition: 2.6s cubic-bezier(0.68, -0.55, 0.265, 1.55);*/
   background-clip: border-box;
   transform-origin: top left;
   overflow-y:auto;
}
.page::first-line{color:#888;font-weight:bold; font-size:26px;}

@keyframes bounce-li{
  0%  {transform:  translate(0%,100%);animation-timing-function: ease-out;  }
  40%  {transform:  translate(0%,100%);animation-timing-function: ease-out;  }
 100% {transform:  translate(0%,0%); animation-timing-function: ease-in; }
}

@keyframes bounce-lo{
  0%  {transform:  translate(0%,0%);animation-timing-function: ease-out;  }
  40%  {transform:  translate(0%,0%);animation-timing-function: ease-out;  }
  100% {transform:  translate(0%,calc(-100% - 40px)); animation-timing-function: ease-in; }
}

@keyframes bounce-ri{
  0%  {transform:  translate(0%,calc(-100% - 40px));animation-timing-function: ease-out;  }
  40%  {transform:  translate(0%,calc(-100% - 40px));animation-timing-function: ease-out;  }
  100% {transform:  translate(0%,0%); animation-timing-function: ease-in; }
}

@keyframes bounce-ro{
  0%  {transform:  translate(0%,0%);animation-timing-function: ease-out;  }
  40%  {transform:  translate(0%,0%);animation-timing-function: ease-out;  }
  100% {transform:  translate(0%,calc(100% + 40px)); animation-timing-function: ease-in; }
}



.container{
  box-sizing: border-box;
 ...

JavaScript

///////// pMenu //////////
var pMenu = Vue.extend({
  template: '#pMenu',
  data:function(){
  	return {
    		page:'page1',
        isActive:false,
        timeoutId:null,
    		items:['page1','page2','page3','page4']
        }
  },
  methods:{
  	click:function(item){
      var isR=this.items.indexOf(item)>this.items.indexOf(this.page);
    	this.page=item;
      vv.transitionName=isR?'pageL':'pageR';
      vv.page=item;
    },
 		isFocused:function(item){
    	return item==this.page?'focused':''
    }   
  },
  watch: {
    page: function(newValue) {
      clearTimeout(this.timeoutId);
      this.isActive=true;
      var self=this;
      this.timeoutId = setTimeout(function(){ self.isActive=false; }, 1000);
    }
  }
})
Vue.component('p-menu', pMenu);

/////////// PAGE 1 ///////////////
Vue.component('page1', {  template: '#page1',
  data:function(){
  	return {
    		transitionName:'pageS',
    		subpage:'subpage1',
        checked:false,
        page:"",
    		items:['page1','page2','page3','page4'],
    		nextNum: 10
        }
  },
  methods: {
    randomIndex: function () {
      return Math.floor(Math.random() * this.items.length)
    },
    add: function () {
      this.items.splice(this.randomIndex(), 0, "page"+this.nextNum++)
    },
    remove: function () {
      this.items.splice(this.randomIndex(), 1)
    },
    clicked(item){
      const index=this.items.indexOf(item);
      if(index==0){
      	if(this.page==item)
        	this.page="pageEmpty";
        else
      		this.page=item;
      }else{
      	this.items.splice(index, 1);
      	this.items.splice(0, 0, item); 
        this.page="pageEmpty";
        if(this.checked)
	        this.page=item;
      }
    },
  }});  
/////////// PAGE 2 ///////////////
Vue.component('page2', {  template: '#page2'});  
/////////// PAGE 3 ///////////////
Vue.component('page3', {  template: '#page3'});  
/////////// PAGE 3 ///////////////
Vue.component('page4', {  template: '#page4'});  
/////////// PAGE 3...