UNPKG

can

Version:

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

210 lines (178 loc) 5.66 kB
<style> label { display: block; margin: 1em 0; } pizza-form > div { width: 20%; float: left; } </style> <pizza-form></pizza-form> <script src="../../node_modules/steal/steal.js" dev-bundle main="@empty" id="demo-source"> import { ObservableArray, stacheConverters, StacheElement, type } from "can"; class SelectOne extends StacheElement { static view = ` <div> <p>Select {{ this.listName }}:</p> <select value:from="default" on:change="this.update(this.listName, 'toggle', scope.element.value)"> {{# for(option of this.options) }} <option>{{ option }}</option> {{/ for }} </select> </div> `; static props = { listName: { type: type.maybeConvert(String), default: "one" }, options: type.maybeConvert(ObservableArray), default: type.maybeConvert(String), update: Function }; }; customElements.define("select-one", SelectOne); class SelectMany extends StacheElement { static view = ` <div> <p>Select {{ this.listName }}:</p> {{# for(option of this.options) }} <label> {{ option }} <input on:change="this.update(this.listName, 'toggle', option)" type="checkbox"> </label> {{/ for }} </div> `; static props = { listName: { type: type.maybeConvert(String), default: "many" }, options: type.maybeConvert(ObservableArray), update: Function }; }; customElements.define("select-many", SelectMany); class MeatPicker extends StacheElement { static view = ` {{ let showOptions=null }} <div> <label> Vegetarian <input checked:bind="not( showOptions )" on:change="this.update('meats', 'clear')" type="checkbox"> </label> {{# if(showOptions) }} <select-many update:from="this.update" listName:raw="meats" options:from="this.options"> </select-many> {{/ if }} </div> `; static props = { update: Function }; }; customElements.define("meat-picker", MeatPicker); class PizzaForm extends StacheElement { static view = ` <p> Selected Ingredients: {{# for(meat of this.selectedMeats) }} {{ meat }}, {{/ for }} {{# for(veggie of this.selectedVegetables) }} {{ veggie }}, {{/ for }} {{# if(this.selectedCheese) }} {{ this.selectedCheese }} cheese {{/ if }} </p> <div> <select-one listName:raw="cheese" update:from="this.updateIngredients" default:from="this.selectedCheese" options:from="this.availableCheeses"> </select-one> </div> <div> <meat-picker update:from="this.updateIngredients" options:from="this.availableMeats"> </meat-picker> </div> <div> <select-many listName:raw="vegetables" update:from="this.updateIngredients" options:from="this.availableVegetables"> </select-many> </div> `; static props = { availableVegetables: { get default() { return [ "green peppers", "mushrooms", "onion", "tomato" ]; } }, availableMeats: { get default() { return [ "chicken", "sausage", "pepperoni" ]; } }, availableCheeses: { get default() { return [ "cheddar", "mozzarella", "parmesan", "provolone" ]; } }, selectedVegetables: { type: type.maybeConvert(ObservableArray), get default() { return new ObservableArray(); } }, selectedMeats: { type: type.maybeConvert(ObservableArray), get default() { return new ObservableArray(); } }, selectedCheese: { type: type.maybeConvert(String), default: "mozzarella" } }; updateIngredients(type, action, ingredient) { let listName = "selected" + type.slice(0, 1).toUpperCase() + type.slice(1); let index = this[listName].indexOf(ingredient); switch(action) { case "add": if (typeof this[listName] === "string") { this[listName] = ingredient; } else { this[listName].push(ingredient); } break; case "remove": if (typeof this[listName] === "string") { this[listName] = ""; } else { this[listName].splice(index, 1); } break; case "toggle": if (index >= 0) { this.updateIngredients(type, "remove", ingredient); } else { this.updateIngredients(type, "add", ingredient); } break; case "clear": this[listName] = []; break; } } }; customElements.define("pizza-form", PizzaForm); </script>