UNPKG

can

Version:

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

156 lines (148 loc) 3.43 kB
<style type="text/css"> body {font-family: verdana} my-tabs { margin-top: 20px; } button {clear: both;} my-tabs ul { padding: 0px; margin: 0px; } my-tabs li { float: left; padding: 10px; background-color: #F6F6F6; list-style: none; margin-left: 10px; } my-tabs li { color: #1C94C4; font-weight: bold; text-decoration: none; } my-tabs li.active { color: #F6A828; cursor: default; } my-panel { clear: both; display: block; } /* clearfix from jQueryUI */ my-tabs ul:after { content: "."; display: block; height: 1px; clear: both; visibility: hidden; } my-tabs ul { display: inline-block; } </style> <my-app id="out"></my-app> <script src="../../node_modules/steal/steal.js" dev-bundle main="@empty" id="demo-source"> import { Component, queues } from "can"; Component.extend({ tag: "my-tabs", view:` <ul> {{# for(panel of this.panels) }} <li {{# this.isActive(panel) }}class='active'{{/ }} on:click='this.makeActive(panel)'> {{ panel.title }} </li> {{/ for }} </ul> <content></content>`, ViewModel: { // Contains a list of all panel scopes within the // tabs element. panels: { default: () => [] }, active: "any", // When a `<my-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 `<my-panel>` element is removed from the document, // it calls this method to remove the panel's viewModel from // the panels array. removePanel: function(panel){ const panels = this.panels; queues.batch.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; } } queues.batch.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({ view: "{{# if(this.active) }}<content></content>{{/ if }}", tag:"my-panel", ViewModel: { active: { type: "boolean", default: false }, connectedCallback: function(element) { const panel = this; const parentViewModel = element.parentNode.viewModel; parentViewModel.addPanel(panel); return () => { this.stopListening(); parentViewModel.removePanel(panel); }; } } }); Component.extend({ tag: "my-app", view: ` <p> <button on:click="this.addVegies()">Add Vegetables</button> </p> <my-tabs> {{# for(foodType of this.foodTypes) }} <my-panel title:from='foodType.title'> {{ foodType.content }} </my-panel> {{/ for }} </my-tabs> `, ViewModel: { foodTypes: { default(){ return [ {title: "Fruits", content: "oranges, apples"}, {title: "Breads", content: "pasta, cereal"}, {title: "Sweets", content: "ice cream, candy"} ]; } }, addVegies(){ this.foodTypes.push({ title: "Vegetables", content: "Carrots, peas, kale" }); } } }); </script>