BB: Card Collection

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/backbone.js/1.2.2/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone-localstorage.js/1.1.16/backbone.localStorage-min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.js"></script>
<h1>Welcome</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Perferendis ipsam quas illo aperiam at doloremque tempore rerum nostrum, sequi, voluptas delectus numquam hic, sit nobis perspiciatis ab. Dolores, dicta, at!</p>

<div class="js-app"></div>


<script type="text/x-handlebars-template" class="tmpl-canvas">
	<div class="canvas__controls">
		<button class="btn btn--add-card push--right push  js-action--add-card" disabled>+ Add</button>
	</div>
    <br>
    <h3>Order list</h3>
	<div class="js-region--cards">
		<!-- .grid -->
	</div>
</script>

<script type="text/x-handlebars-template" class="tmpl-card--layout">
	<header class="rb-card__header">
		<h1>{{type}}</h1>
	</header>
	<div class="js-region--contents">
        <div class="js-region--orders"></div>
		<div class="js-region--order"></div>
	</div>
</script>

<script type="text/x-handlebars-template" class="tmpl-order--single">
	Order name: {{name}}
</script>

<script type="text/x-handlebars-template" class="tmpl-order--detailed">
	<h1>Order Details screen for {{name}}</h1>
</script>

SCSS

$commonui-button-color--negative: #D60101 !default;
$commonui-brand-color--neutral__grey-lightest: rgb(218,223,225) !default;
$commonui-font-color-on-dark: #FFF !default;
$commonui-base-radius-unit: 4px;
$commonui-link-color: #1971C4 !default;

.rb-card {
	border: 1px solid rgba(black, 0.1);
	padding: 5px;
	
	&__header {
		display: flex;
		justify-content: space-between;
	}
}

.canvas__controls {
	display: flex;
	justify-content: flex-end;
}

.btn {
	display: inline-block;
    vertical-align: middle;
    font: inherit;
    text-align: center;
    margin: 0;
    cursor: pointer;
    overflow: visible;
    padding: 5px 11px;
    background-color: #0195E7;
    border: 1px solid #0195E7;
    border-radius: 4px;
	color: white;
	margin-bottom: 10
}


.cell {
    $cellPadding: 4px !default;

    border-bottom: 2px solid $commonui-brand-color--neutral__grey-lightest;
    display: flex;
    justify-content: space-between;
    padding: $cellPadding 0;
    cursor: pointer;
    overflow: hidden;
    position: relative;
    opacity: 1;
    transition: opacity .3s;

    &:first-child {
        border-top: 2px solid $commonui-brand-color--neutral__grey-lightest;
    }

    &:hover {
        opacity: 0.75;
    }
    
    .is-loading & {
        background: lightGreen;
    }

    &__details {
        display: flex;
        flex: 1;
        align-items: center;
    }

    &__label {
        background: $commonui-button-color--negative;
        color: $commonui-font-color-on-dark;
        position: absolute;
        top: 0;
        left: 0;
    }

    &__column {
        flex: 0 1 50%;
    }

    &__columns {
        display: flex;
        border: 2px solid $commonui-brand-color--neutral__grey-lightest;
        border-radius: $commonui-base-radius-unit;
        @include commonui-font-size(12px, 16px);
        align-items: center;
        flex: 0 1 100px;
        justify-content: space-around;
    }

    &--sell {
        .cell__label {
            background-color:...

JavaScript

console.clear();

var cardData = {
	"type":"preference", 
	"info": {
		"cards": [
			{
				"id": "1234", 
				"type": "Orders"
			}, 
			{
				"id": "5678", 
				"type": "Markets"
			}
		]
	}
};

var orderData = [{
   "name": "Order 1"
}, {
    "name": "Order 2"
}];

var App = {
	M: {},
	V: {},
	C: {},
	utils: {},
	start: function() {
		var cards = new App.C.Cards(cardData, { parse: true });
				
		var canvasLayout = new App.V.CanvasLayout({
			collection: cards,
			childView: '.js-region--cards'
		});
		
		$('.js-app').append( canvasLayout.render().el );
	}
};

// Models
App.M.Card = Backbone.Model.extend();
App.M.Order = Backbone.Model.extend();

// Collection
App.C.Cards = Backbone.Collection.extend({
	model: App.M.Card,
    
    parse: function(response) {
    	return response.info.cards;
    }
});
App.C.Orders = Backbone.Collection.extend({
	model: App.M.Order
});

/**
 *	Acts as a layout view with multiple regions.
 */
App.V.CanvasLayout = Backbone.View.extend({
	
	className: 'canvas',
	
	events: {
		'click .js-action--add-card': 'addCardBtnClicked'	
	},
	
	regions: {},
	
	template: _.template( $('.tmpl-canvas').html() ),
	
	initialize: function(options) {		
		this.options = options;
	},
	
	render: function() {
		this.$el.html( this.template() );
		
		setTimeout(function() {
			this.onRender();
		}.bind(this), 0);
		
		return this;
	},
	
	onRender: function() {
		
		this.regions.cards = this.$(this.options.childView);
		
		var cards = new App.V.Cards({
			collection: this.collection
		});
		
		this.regions.cards.html(cards.render().el);
	},
	
	destroy: function() {
		this.remove();
	}
});

App.V.Cards = Backbone.View.extend({
	
	className: 'grid',
	
	isRendered: false,
	
	initialize: function() {
		this.fragment = document.createDocumentFragment();
		
		this.listenTo(this.collection, 'add', this.addCard, this);
	},
	
	render: function() {	
    	this.collection.forEach(this.addCard, this);
		
		this.$el.html(this.fragment);
		
		setTimeout(function()...