Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/html/lib/layout/tree/source/Node.js
diff options
context:
space:
mode:
Diffstat (limited to 'html/lib/layout/tree/source/Node.js')
-rw-r--r--html/lib/layout/tree/source/Node.js269
1 files changed, 269 insertions, 0 deletions
diff --git a/html/lib/layout/tree/source/Node.js b/html/lib/layout/tree/source/Node.js
new file mode 100644
index 0000000..ff79c9a
--- /dev/null
+++ b/html/lib/layout/tree/source/Node.js
@@ -0,0 +1,269 @@
+/**
+ _enyo.Node_ is a control that creates structured trees based on Enyo's child
+ component hierarchy format, e.g.:
+
+ {kind: "Node", icon: "images/folder-open.png", content: "Tree",
+ expandable: true, expanded: true, components: [
+ {icon: "images/file.png", content: "Alpha"},
+ {icon: "images/folder-open.png", content: "Bravo",
+ expandable: true, expanded: false, components: [
+ {icon: "images/file.png", content: "Bravo-Alpha"},
+ {icon: "images/file.png", content: "Bravo-Bravo"},
+ {icon: "images/file.png", content: "Bravo-Charlie"}
+ ]
+ }
+ ]
+ }
+
+ The default kind of components within a node is itself _enyo.Node_, so only
+ the top-level node of the tree needs to be explicitly defined as such.
+
+ When an expandable tree node expands, an _onExpand_ event is sent; when it
+ is tapped, a _nodeTap_ event is sent.
+
+ When the optional property _onlyIconExpands_ is set to true, expandable
+ nodes may only be opened by tapping the icon; tapping the content label
+ will fire the _nodeTap_ event, but will not expand the node.
+*/
+
+enyo.kind({
+ name: "enyo.Node",
+ published: {
+ //* @public
+ //* Whether or not the Node is expandable and has child branches
+ expandable: false,
+ //* Open/closed state of the current Node
+ expanded: false,
+ //* Path to image to be used as the icon for this Node
+ icon: "",
+ /**
+ Optional flag that, when true, causes the Node to expand only when
+ the icon is tapped; not when the contents are tapped
+ */
+ onlyIconExpands: false,
+ //* @protected
+ //* Adds or removes the Enyo-selected CSS class.
+ selected: false
+ },
+ style: "padding: 0 0 0 16px;",
+ content: "Node",
+ defaultKind: "Node",
+ classes: "enyo-node",
+ components: [
+ {name: "icon", kind: "Image", showing: false},
+ {kind: "Control", name: "caption", Xtag: "span", style: "display: inline-block; padding: 4px;", allowHtml: true},
+ {kind: "Control", name: "extra", tag: 'span', allowHtml: true}
+ ],
+ childClient: [
+ {kind: "Control", name: "box", classes: "enyo-node-box", Xstyle: "border: 1px solid orange;", components: [
+ {kind: "Control", name: "client", classes: "enyo-node-client", Xstyle: "border: 1px solid lightblue;"}
+ ]}
+ ],
+ handlers: {
+ ondblclick: "dblclick"
+ },
+ events: {
+ //* @public
+ //* Fired when the Node is tapped
+ onNodeTap: "nodeTap",
+ //* Fired when the Node is double-clicked
+ onNodeDblClick: "nodeDblClick",
+ /**
+ Fired when the Node expands or contracts, as indicated by the
+ 'expanded' property in the event data
+ */
+ onExpand: "nodeExpand",
+ //* Fired when the Node is destroyed
+ onDestroyed: "nodeDestroyed"
+ },
+ //
+ //* @protected
+ create: function() {
+ this.inherited(arguments);
+ //this.expandedChanged();
+ //this.levelChanged();
+ this.selectedChanged();
+ this.iconChanged();
+ },
+ destroy: function() {
+ this.doDestroyed();
+ this.inherited(arguments);
+ },
+ initComponents: function() {
+ // TODO: optimize to create the childClient on demand
+ //this.hasChildren = this.components;
+ if (this.expandable) {
+ this.kindComponents = this.kindComponents.concat(this.childClient);
+ }
+ this.inherited(arguments);
+ },
+ //
+ contentChanged: function() {
+ //this.$.caption.setContent((this.expandable ? (this.expanded ? "-" : "+") : "") + this.content);
+ this.$.caption.setContent(this.content);
+ },
+ iconChanged: function() {
+ this.$.icon.setSrc(this.icon);
+ this.$.icon.setShowing(Boolean(this.icon));
+ },
+ selectedChanged: function() {
+ this.addRemoveClass("enyo-selected", this.selected);
+ },
+ rendered: function() {
+ this.inherited(arguments);
+ if (this.expandable && !this.expanded) {
+ this.quickCollapse();
+ }
+ },
+ //
+ addNodes: function(inNodes) {
+ this.destroyClientControls();
+ for (var i=0, n; n=inNodes[i]; i++) {
+ this.createComponent(n);
+ }
+ this.$.client.render();
+ },
+ addTextNodes: function(inNodes) {
+ this.destroyClientControls();
+ for (var i=0, n; n=inNodes[i]; i++) {
+ this.createComponent({content: n});
+ }
+ this.$.client.render();
+ },
+ //
+ tap: function(inSender, inEvent) {
+ if(!this.onlyIconExpands) {
+ this.toggleExpanded();
+ this.doNodeTap();
+ } else {
+ if((inEvent.target==this.$.icon.hasNode())) {
+ this.toggleExpanded();
+ } else {
+ this.doNodeTap();
+ }
+ }
+ return true;
+ },
+ dblclick: function(inSender, inEvent) {
+ this.doNodeDblClick();
+ return true;
+ },
+ //
+ toggleExpanded: function() {
+ this.setExpanded(!this.expanded);
+ },
+ quickCollapse: function() {
+ this.removeClass("enyo-animate");
+ this.$.box.applyStyle("height", "0");
+ var h = this.$.client.getBounds().height;
+ this.$.client.setBounds({top: -h});
+ },
+ _expand: function() {
+ this.addClass("enyo-animate");
+ var h = this.$.client.getBounds().height;
+ this.$.box.setBounds({height: h});
+ this.$.client.setBounds({top: 0});
+ setTimeout(enyo.bind(this, function() {
+ // things may have happened in the interim, make sure
+ // we only fix height if we are still expanded
+ if (this.expanded) {
+ this.removeClass("enyo-animate");
+ this.$.box.applyStyle("height", "auto");
+ }
+ }), 225);
+ },
+ _collapse: function() {
+ // disable transitions
+ this.removeClass("enyo-animate");
+ // fix the height of our box (rather than 'auto'), this
+ // gives webkit something to lerp from
+ var h = this.$.client.getBounds().height;
+ this.$.box.setBounds({height: h});
+ // yield the thead so DOM can make those changes (without transitions)
+ setTimeout(enyo.bind(this, function() {
+ // enable transitions
+ this.addClass("enyo-animate");
+ // shrink our box to 0
+ this.$.box.applyStyle("height", "0");
+ // slide the contents up
+ this.$.client.setBounds({top: -h});
+ }), 25);
+ },
+ expandedChanged: function(inOldExpanded) {
+ if (!this.expandable) {
+ this.expanded = false;
+ } else {
+ var event = {expanded: this.expanded};
+ this.doExpand(event);
+ if (!event.wait) {
+ this.effectExpanded();
+ }
+ }
+ },
+ effectExpanded: function() {
+ if (this.$.client) {
+ if (!this.expanded) {
+ this._collapse();
+ } else {
+ this._expand();
+ }
+ }
+ //this.contentChanged();
+ }/*,
+ //
+ //
+ levelChanged: function() {
+ this.applyStyle("padding-left", 16 + "px");
+ },
+ toggleChildren: function() {
+ if (this.$.list) {
+ this.$.list.setShowing(this.expanded);
+ }
+ },
+ renderNodes: function(inNodes) {
+ var list = this.createComponent({name: "list", container: this});
+ for (var i=0, n; n=inNodes[i]; i++) {
+ n.setLevel(this.level + 1);
+ n.setContainer(list);
+ n.render();
+ }
+ list.render();
+ },
+ //* @public
+ addNodes: function(inNodes) {
+ this.renderNodes(inNodes);
+ this.toggleChildren();
+ },
+ removeNodes: function() {
+ if (this.$.list) {
+ this.$.list.destroy();
+ }
+ },
+ hasVisibleChildren: function() {
+ return this.expanded && this.$.list && this.$.list.controls.length > 0;
+ },
+ fetchParent: function() {
+ return this.level > 0 && this.container.container;
+ },
+ fetchChildren: function() {
+ return this.$.list && this.$.list.controls;
+ },
+ fetchFirstChild: function() {
+ return this.$.list && this.$.list.controls[0];
+ },
+ fetchLastChild: function() {
+ return this.$.list && this.$.list.controls[this.$.list.controls.length-1];
+ },
+ fetchPrevSibling: function() {
+ var i = this.container.controls.indexOf(this);
+ return this.level > 0 && this.container.controls[i-1];
+ },
+ fetchNextSibling: function() {
+ var i = this.container.controls.indexOf(this);
+ return this.level > 0 && this.container.controls[i+1];
+ },
+ getVisibleBounds: function() {
+ return this.$.client.getBounds();
+ }
+ */
+}); \ No newline at end of file