Skip to content

Instantly share code, notes, and snippets.

@aaronanderson
Last active May 29, 2017 23:28
Show Gist options
  • Save aaronanderson/553de211642ceb2658e8fddc6eb1daf1 to your computer and use it in GitHub Desktop.
Save aaronanderson/553de211642ceb2658e8fddc6eb1daf1 to your computer and use it in GitHub Desktop.
A Polymer 2.0 collapsible tree using a caller provided template
<link rel="import" href="../polymer/polymer-element.html">
<link rel="import" href="../iron-collapse/iron-collapse.html">
<link rel="import" href="../paper-item/paper-icon-item.html">
<link rel="import" href="../paper-item/paper-item-body.html">
<link rel="import" href="../iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="../iron-icons/iron-icons.html">
<link rel="import" href="../iron-icon/iron-icon.html">
<dom-module id="intworkspace-tree">
<template>
<style include="iron-flex iron-flex-alignment">
paper-icon-item {
--paper-item-min-height: var(--intworkspace-tree-margin,30px);
--paper-item-icon-width : var(--intworkspace-tree-margin,30px);
}
paper-icon-item:focus::before,
paper-icon-item:focus::after {
color: inherit;
opacity: 0;
}
.node {
margin-left: var(--intworkspace-tree-margin,30px);;
}
</style>
<slot id="labelView"></slot>
</template>
<template id="nodeView">
<template is="dom-repeat" items="{{tree}}" as="node" index-as="n">
<div class="layout vertical">
<!--<div>index: [[n]]</div>
<div>name: [[node.name]]</div>-->
<paper-icon-item on-tap="nodeSelected">
<template is="dom-if" if="[[hasNodes(node)]]">
<iron-icon icon="expand-less" slot="item-icon" hidden$="[[!hasNodes(node)]]"></iron-icon>
</template>
<!-- label goes here-->
</paper-icon-item>
<template is="dom-if" if="[[hasNodes(node)]]">
<iron-collapse class="node" opened>
<intworkspace-tree tree="[[node.nodes]]" node-template="[[nodeTemplate]]" embedded></intworkspace-tree>
</iron-collapse>
</template>
</div>
</template>
</template>
<script>
class IntTree extends Polymer.TemplateStamp(Polymer.Element) {
static get is() {
return 'intworkspace-tree';
}
static get properties() {
return {
tree: {
type: Array,
value: []
},
nodeTemplate: {
type: Object,
}
};
}
ready() {
super.ready();
if (!this.hasAttribute("embedded")) {
let labelTemplate = this.$.labelView.assignedNodes().find((e) => {
return e instanceof HTMLTemplateElement;
});
let nodeTemplate = document.importNode(Polymer.DomModule.import(IntTree.is, "#nodeView"), true);
let repeatTemplate = nodeTemplate.content.querySelector("template[is='dom-repeat']");
let iconItem = repeatTemplate.content.querySelector('paper-icon-item');
iconItem.appendChild(labelTemplate.content);
this.nodeTemplate = nodeTemplate;
}
let nodeInstance = this._stampTemplate(this.nodeTemplate);
this.shadowRoot.appendChild(nodeInstance);
}
hasNodes(node) {
return node.nodes != null && node.nodes.length > 0;
}
nodeSelected(e) {
let collapse = e.currentTarget.parentNode.querySelector("iron-collapse");
let nodeIcon = e.currentTarget.parentNode.querySelector("iron-icon");
if (collapse && nodeIcon) {
collapse.toggle();
if (collapse.opened) {
nodeIcon.icon = "expand-less";
} else {
nodeIcon.icon = "expand-more";
}
}
}
}
window.customElements.define(IntTree.is, IntTree);
</script>
</dom-module>
<link rel="import" href="../polymer/polymer-element.html">
<!--<link rel="import" href="../polymer/lib/elements/dom-if.html">-->
<!--<link rel="import" href="../polymer/lib/elements/dom-repeat.html">-->
<link rel="import" href="../paper-item/paper-item-body.html">
<link rel="import" href="../paper-button/paper-button.html">
<link rel="import" href="intworkspace-tree.html">
<!--
`tree-test`
@demo demo/index.html
-->
<dom-module id="tree-test">
<template>
<style>
:host {
display: block;
}
</style>
<intworkspace-tree tree="{{testTree}}">
<template preserve-content><paper-item-body>[[node.name]]</paper-item-body></template>
</intworkspace-tree>
<div>
<paper-button raised on-tap="reload">Reload</paper-button>
</div>
</template>
<script>
/** @polymerElement */
class TreeTest extends Polymer.Element {
static get is() {
return 'tree-test';
}
random(min, max) {
return Math.random() * (max - min) + min;
}
createLevel(newTree, currentDepth) {
if (currentDepth == 3) {
return;
}
var numNodes = this.random(currentDepth == 0 ? 1 : 0, 4);
var newDepth = currentDepth + 1;
for (var i = 1; i <= numNodes; i++) {
var id = this.testNodeId++;
var childTree = [];
this.createLevel(childTree, newDepth);
var node = {
id: id,
name: `Node ${id}`,
nodes: childTree
}
newTree.push(node);
}
}
reload() {
this.testNodeId = 1;
var newTree = [];
this.createLevel(newTree, 0);
console.log("new tree", JSON.stringify(newTree));
this.set("testTree", newTree);
}
static get properties() {
return {
testTree: {
type: Array,
value: []
},
testNodeId: {
type: Number
}
};
}
ready() {
super.ready();
this.reload();
}
}
window.customElements.define(TreeTest.is, TreeTest);
</script>
</dom-module>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment