demos/can-component/accordion.html
<div id="out"></div>
<script src="../../node_modules/steal/steal.js" dev-bundle main="@empty">
import { Component, stache, DefineMap, DefineList, viewModel} from "can";
const demoHTML = `<my-accordion>
<my-panel makeActive:from="makeActive" title:from="'Contacts'">
<button>Change title attribute to "Users"</button>
<ul>
<li>Justin</li>
<li>Brian</li>
</ul>
</my-panel>
<my-panel makeActive:from="makeActive" title:from="'Libraries'">
<ul>
<li>CanJS</li>
<li>JavaScriptMVC</li>
</ul>
</my-panel>
</my-accordion>`;
const Panel = DefineMap.extend({
active: "boolean",
title: "string"
});
const AccordionViewModel = DefineMap.extend({
active: Panel,
// Contains a list of all panel scopes within the
// tabs element.
panels: {
Default: DefineList
},
// When a `<panel>` element is inserted into the document,
// it calls this method to add the panel's scope 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 scope from
// the panels array.
removePanel: function(panel){
var panels = this.panels;
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;
}
}
},
makeActive: function(panel){
this.active = panel;
this.panels.forEach(function(panel){
panel.active = false;
});
panel.active = true;
}
});
Component.extend({
tag: "my-accordion",
ViewModel: AccordionViewModel,
leakScope: true
});
Component.extend({
tag:"my-panel",
view: `
<h2 on:click='makeActive(this)'>{{ title }}</h2>
{{# if(active) }}<content></content>{{/ if }}`,
ViewModel: DefineMap.extend('MyPanelVM', {
active: {
type: "boolean",
default: false
},
title: "string",
connectedCallback: function(element) {
var panel = this;
var parentViewModel = element.parentNode.viewModel;
parentViewModel.addPanel(panel);
return function() {
parentViewModel.removePanel(panel);
};
}
})
});
var out = document.getElementById("out");
var template = stache(demoHTML);
out.appendChild(template({}));
out.addEventListener("click", function(ev){
var el = ev.target;
var parent = el.parentNode.viewModel;
if (el.nodeName === "BUTTON") {
parent.title = "Users";
}
});
window.canViewModel = viewModel;
</script>