UNPKG

can

Version:

MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.

164 lines (153 loc) 3.82 kB
<style type="text/css"> body {font-family: verdana} tabs { margin-top: 20px; } button {clear: both;} tabs ul { padding: 0px; margin: 0px; } tabs li { float: left; padding: 10px; background-color: #F6F6F6; list-style: none; margin-left: 10px; } tabs li { color: #1C94C4; font-weight: bold; text-decoration: none; } tabs li.active { color: #F6A828; cursor: default; } panel { clear: both; display: block; } /* clearfix from jQueryUI */ tabs ul:after { content: "."; display: block; height: 1px; clear: both; visibility: hidden; } tabs ul { display: inline-block; } </style> <div id="demo-html"> <div id='out'></div> <script id="app" type="text/stache"> <p><button can-click="addVegies">Add Vegetables</button></p> <tabs> {{#each foodTypes}} <panel title='{{title}}'>{{content}}</panel> {{/each}} </tabs> </script> </div> <script src="../../node_modules/steal/steal.js" main="@empty" id="demo-source"> var Component = require("can-component"); var stache = require("can-stache"); var DefineMap = require("can-define/map/map"); var DefineList = require("can-define/list/list"); var canViewModel = require("can-view-model"); var canBatch = require("can-event/batch/batch"); var Panel = DefineMap({ active: "boolean" }); var PanelList = DefineList.extend({ "#": Panel }); var ViewModel = DefineMap.extend({ // Contains a list of all panel scopes within the // tabs element. panels: { value: PanelList.extend({}) }, active: { Type: Panel }, // When a `<panel>` element is inserted into the document, // it calls this method to add the panel's viewModel to the // panels array. addPanel: function(panel){ // If this is the first panel, activate it. if( this.panels.length === 0 ) { this.makeActive(panel) } this.panels.push(panel); }, // When a `<panel>` element is removed from the document, // it calls this method to remove the panel's viewModel from // the panels array. removePanel: function(panel){ var panels = this.panels; canBatch.start(); panels.splice(panels.indexOf(panel),1); // if the panel was active, make the first item active if(panel === this.active){ if(panels.length){ this.makeActive(panels[0]); } else { this.active = undefined; } } canBatch.stop() }, makeActive: function(panel){ this.active = panel; this.panels.forEach(function(panel){ panel.active = false; }); panel.active = true; }, // this is viewModel, not mustache // consider removing viewModel as arg isActive: function( panel ) { return this.active === panel; } }); Component.extend({ tag: "tabs", template: stache("<ul>"+ // Create an LI for each item in the panel's viewModel object "{{#panels}}"+ "<li {{#isActive}}class='active'{{/isActive}} "+ "($click)='makeActive(.)'>"+ "{{title}}"+ "</li>"+ "{{/panels}}"+ "</ul>"+ "<content></content>"), ViewModel: ViewModel }); Component.extend({ template: stache("{{#if active}}<content></content>{{/if}}"), tag:"panel", ViewModel: Panel, events: { inserted: function(){ var vm = this.parentViewModel = canViewModel(this.element.parentNode); vm.addPanel(this.viewModel); }, removed: function(){ this.parentViewModel.removePanel(this.viewModel); } } }); var foodTypes = new DefineList([ {title: "Fruits", content: "oranges, apples"}, {title: "Breads", content: "pasta, cereal"}, {title: "Sweets", content: "ice cream, candy"} ]); window.foodTypes = foodTypes; var template = document.getElementById("app").innerHTML; var frag = stache(template)({ foodTypes: foodTypes, addVegies: function(){ foodTypes.push({ title: "Vegetables", content: "Carrots, peas, kale" }); } }); document.getElementById("out").appendChild(frag); </script>