BB: Panel View

by kyllle

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-alpha1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.css">
<header class="main-header">
    <button class="js-action--show">Show</button>
    <button class="js-action--hide">Hide</button>
</header>

<script type="text/template" class="tmpl-scroller">
    <div class="scroller__content  js-region--scroll"></div>
</script>

<script type="text/template" class="tmpl-content">
	<h1>Card content</h1>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Culpa quisquam, harum animi, eius recusandae quos fuga, quibusdam nam facilis sit ad repudiandae fugiat nesciunt nostrum sed quaerat laboriosam nihil architecto.</p>
</script>

SCSS

* {
  -webkit-font-smoothing: antialiased;
}

html, body {
    height: 100%;
}

.scroller {
	height: 100%;
	width: 100%;

	&__content {
		-webkit-user-select: none;
		-webkit-overflow-scrolling: touch;
		overflow-y: scroll;
		transform: translateZ(0);
		height: 100%;
	}
}

.anim-slide {
    position: absolute;
    transition: transform .3s ease;

    &--from-top,
    &--from-bottom {
        &.is-animating {
            transform: translateY(0);
        }
    }

    &--from-top {
        transform: translateY(-100%);
        top: 0;
    }

    &--from-bottom {
        transform: translateY(100%);
        bottom: 0;      
    }
    
    &--from-left,
    &--from-right {
        top: 0;

        &.is-animating {
            transform: translateX(0);
        }
    }

    &--from-left {
        transform: translateX(-100%);
        right: 0;
    }

    &--from-right {
        transform: translateX(100%);
        left: 0;
    }
    
    &--override {
        transition: none;
    }
}

.scroller {
    background: #eee;
}

.main-header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    background: #ddd;
    padding: 6px;
    z-index: 10;
}

Babel + JSX

console.clear();

(() => {
const ScrollerView = Backbone.View.extend({

	className: 'anim-slide scroller',
    
    stateClasses: {
        isAnimating: 'is-animating'
    },
    
    template: Handlebars.compile($('.tmpl-scroller').html()),
    
    offsetAllowList: ['top', 'right', 'bottom', 'left'],
    
    initialize(options) {
        this.options = options || {};
        
        // Should probably live in a model.
        if(this.options.offset && _.contains(this.offsetAllowList, this.options.offset)) {
        	const offsetClass = ' anim-slide--from-'.concat(this.options.offset);
            this.el.className += offsetClass;
        } else {
        	this.el.className += ' anim-slide--from-bottom';
        }
        
        this.listenTo(this, 'panel.animate:show.complete', this.onShow);
        this.listenTo(this, 'panel.animate:hide.complete', this.onHide);
    },
       
    render() {
        console.log('ScrollerView.render');
        this.$el.html(this.template());
        setTimeout(() => {this.afterRender()}, 0);

        return this;
    },
    
    afterRender() {
        console.log('ScrollerView.afterRender');
    },

    show() {
        console.log('ScrollerView.show');
        this.$el.addClass(this.stateClasses.isAnimating);
        this.$el.one('transitionend', event => this.trigger('panel.animate:show.complete'));
    },

    hide() {
        console.log('ScrollerView.hide');
        this.$el.removeClass(this.stateClasses.isAnimating);
        this.$el.one('transitionend', event => this.trigger('panel.animate:hide.complete'));
    },

    onShow() {
        console.log('ScrollerView.onShow');
    },

    onHide() {
        console.log('ScrollerView.onHide');
                
        setTimeout(() => {this.dispose()}, 0);
    },

    dispose() {
        console.log('ScrollerView.dispose');
        
        if(this.options.childViews) {
        	this.options.childViews.forEach(view => view.dispose());
        }
        
        return...