Tabs Component Recipe

HTML

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script src="http:////canjs.com/release/2.0.4/can.jquery.js"></script>
<script type="text/mustache" id="app-template">
<tabs>
    <panel title="Fruit">Oranges, Apples, Pears</panel>
    <panel title="Vegetable">Carrot, Lettuce, Rutabega</panel>
    <panel title="Grains">Bread, Pasta, Rice</panel>
</tabs>
</script>
<!-- CanJS needs a place to put your application -->
<div id="my-app"></div>

CSS

ul {
    list-style: none;
    padding-left: 0px;
}
li{
    display: inline-block;
    padding: 5px;
    border: 1px solid black;
    -webkit-border-top-left-radius: 8px;
    -webkit-border-top-right-radius: 8px;
    -moz-border-radius-topleft: 8px;
    -moz-border-radius-topright: 8px;
    border-top-left-radius: 8px;
    border-top-right-radius: 8px;
    cursor: pointer;
}
.panelcontent {
    border: 1px solid black;
}

JavaScript

var TabsViewModel = can.Map.extend({
    panels: [],
    active: null,
    addPanel: function( panel ){
        var panels = this.attr("panels");
        panels.push(panel);
        panel.attr("visible", false);
        //activate panel if it is the first one
        if ( panels.attr("length") === 1 ){
            this.activate( panel );
        }
    },
    removePanel: function( panel ){
        var panels = this.attr("panels");
        var index = panels.indexOf(panel);
        panels.splice(index, 1);
        //activate a new panel if panel being removed was the active panel
        if( this.attr("active") === panel ){
            panels.attr("length") ? this.activate(panels[0]) : this.attr("active", null)
        }
    },
    activate: function( panel ){
        var active = this.attr("active")
        if( active !== panel ){
            active && active.attr("visible", false);
            this.attr("active", panel.attr("visible", true));
        }
    }
})

can.Component.extend({
    tag: "tabs",
    scope: TabsViewModel,
    template: "<ul>\
    {{#each panels}}\
    <li can-click='activate'>{{title}}</li>\
    {{/each}}\
    </ul>\
    <content />"
});

can.Component.extend({
	tag: "panel",
	template: "{{#if visible}}<content />{{/if}}",
	scope: {
		title: "@"
	},
	events: {
		inserted: function() {
			this.element.parent().scope().addPanel( this.scope )
		},
		removed: function() {
			this.element.parent().scope().addPanel( this.scope )
		}
	}
});

var frag = can.view("app-template", {});
$("#my-app").html(frag);