vuejs Accordion List

Testing the javascript effects in vuejs, and in response to https://github.com/yyx990803/vue/issues/152

by apasaja

HTML

<script src="http://cdnjs.cloudflare.com/ajax/libs/vue/0.9.2/vue.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js"></script>
<link rel="stylesheet" href="http://getbootstrap.com/dist/css/bootstrap.min.css">
<section id="parent">
    <div class="item panel panel-success" v-repeat="items" v-ref="items" v-component="item">
        <div class="header panel-heading" v-on="click: toggleContent">
             <h3 class="panel-title">{{greet}}</h3>

        </div>
        <div class="content" v-component="content" v-if="contentVisible" v-effect="slide">
            <div class="panel-body">Lorem ipsum...
                <br/>Lorem ipsum...
                <br/>Lorem ipsum...
                <br/>Lorem ipsum...
                <br/>Lorem ipsum...
                <br/>
            </div>
        </div>
    </div>
</section>

CSS

.item {
}
.header {
}
.content {
    overflow: hidden;
}
h3.panel-title {
    font-size: 32px;
}

JavaScript

// Using a basic set of effect
var slideEffects = {
    enter: function (el, insert, timeout) {
        console.log('enter');
        var duration = 0.35; //seconds
        el.style.maxHeight = el.scrollHeight + "px";
        insert();
        TweenMax.to(el, duration, {
            ease: Power4.easeOut,
            maxHeight: el.scrollHeight
        });
    },
    leave: function (el, remove, timeout) {
        console.log('leave');
        var duration = 0.35; //seconds
        el.style.maxHeight = el.scrollHeight + "px";
        TweenMax.to(el, duration, {
            maxHeight: "0",
            padding: "0",
            ease: Power4.easeOut,
            onComplete: remove
        });
    }
};

Vue.component('item', {
    methods: {
        toggleContent: function () {
            //console.log('toggle content');
            this.contentVisible = !this.contentVisible;
            if (this.contentVisible) this.$dispatch('content-visible', this);
        }
    },
    data: {
        greet: "I'm item no ",
        contentVisible: false
    },
    ready: function () {
        this.greet += this.$index;
    },
});

Vue.component('content', {
    data: {},
    effects: {
        slide: slideEffects // used in the source, so putting both
    }
});

var parent = new Vue({
    el: '#parent',
    created: function () {
        this.$on('content-visible', function (item) {
            //console.log("content-visible event received");
            if (this.accordionLike) {
                var items = this.$.items;
                for (i = 0; i < items.length; i++) {
                    var tempItem = items[i];
                    if (tempItem !== item && tempItem.contentVisible) tempItem.contentVisible = false;
                }
            }
        })
    },
    methods: {},
    data: {
        accordionLike: true,
        items: [0, 1, 2, 3, 4, 5]
    }
});