1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2006-2011 Strobe Inc. and contributors. 4 // Portions ©2008-2011 Apple Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 8 /** 9 @namespace 10 11 A tree item is a model object that acts as a node in a tree-like data 12 structure such as a hierarchy of folders or outline of items. This mixin 13 can be applied to tree item model objects to customize the way the tree 14 information is extracted from the object. 15 16 ## Basic Implementation 17 18 If you add this mixin, you must implement the treeItemChildren property so 19 that it returns the current array of child tree items for the receiver. If 20 you do not implement this property the tree item will not function. 21 22 ## Optimizing Branches 23 24 The most common use of this mixin is to override the treeItemBranchIndexes 25 property to return an index set of child items that are themselves branches 26 in the tree. Normally the TreeController will need to walk every item in 27 your list to determine these branch items. However by implementing this 28 method yourself, you can provide a result faster. 29 30 If none of your child items are branches, override this property to return 31 null or an empty index set. 32 33 @since SproutCore 1.0 34 */ 35 SC.TreeItemContent = { 36 37 /** 38 Walk like a duck. 39 40 @type Boolean 41 @default YES 42 */ 43 isTreeItemContent: YES, 44 45 /** 46 Property returns the children for this tree item. The default simply 47 returns null. If you implement this mixin, you MUST implement this 48 property to return the actual tree item children for the item. 49 50 @type SC.Array 51 @default null 52 */ 53 treeItemChildren: null, 54 55 /** 56 The default property used to determine if the tree item is expanded. You 57 can implement you model object to update this property or you can override 58 treeItemDisclosureState() to compute the disclosure state however you 59 want. 60 61 @type Boolean 62 @default YES 63 */ 64 treeItemIsExpanded: YES, 65 66 /** 67 Indicates whether the tree item should be rendered as a group or not. 68 This property is only useful on the root item in your tree. Setting it to 69 YES on any other item will be ignored. 70 71 @type Boolean 72 @default NO 73 */ 74 treeItemIsGrouped: NO, 75 76 /** 77 Returns the disclosure state for the tree item, which appears at the 78 index of the parent's treeItemChildren array. The response must be one of 79 SC.BRANCH_OPEN, SC.BRANCH_CLOSED or SC.LEAF_NODE. 80 81 If the parent parameter is null, then this item is part of the root 82 children array. 83 84 This method will only be called for tree items that have children. Tree 85 items with no children are assumed to be leaf nodes. 86 87 The default implementation uses the treeItemIsExpanded property to 88 determine if the item should be open or closed. 89 90 @param {Object} parent the parent item containing this item 91 @param {Number} idx the index of the item in the parent 92 @returns {Number} branch state 93 */ 94 treeItemDisclosureState: function(parent, idx) { 95 return this.get('treeItemIsExpanded') ? SC.BRANCH_OPEN : SC.BRANCH_CLOSED; 96 }, 97 98 /** 99 Collapse the tree item. The default implementation will change the 100 treeItemIsExpanded property, but you can override this method to handle 101 collapsing anyway you like. 102 103 @param {Object} parent the parent item containing this item 104 @param {Number} idx the index of the item in the parent 105 @returns {void} 106 */ 107 treeItemCollapse: function(parent, idx) { 108 this.setIfChanged('treeItemIsExpanded', NO); 109 }, 110 111 /** 112 Expand the tree item. The default implementation will change the 113 treeItemIsExpanded property, but you can override this method to handle 114 collapsing anyway you like. 115 116 @param {Object} parent the parent item containing this item 117 @param {Number} idx the index of the item in the parent 118 @returns {void} 119 */ 120 treeItemExpand: function(parent, idx) { 121 this.setIfChanged('treeItemIsExpanded', YES); 122 }, 123 124 /** 125 Returns an index set containing the child indexes of the item that are 126 themselves branches. This will only be called on tree items with a branch 127 disclosure state. 128 129 If the passed parent and index are both null, then the receiver is the 130 root node in the tree. 131 132 The default implementation iterates over the item's children to get the 133 disclosure state of each one. Child items with a branch disclosure state 134 will have their index added to the return index set. 135 136 You may want to override this method to provide a more efficient 137 implementation if you are working with large data sets and can infer which 138 children are branches without iterating over each one. 139 140 If you know for sure that all of the child items for this item are leaf 141 nodes and not branches, simply override this method to return null. 142 143 @param {Object} parent the parent item containing this item 144 @param {Number} index the index of the item in the parent 145 @returns {SC.IndexSet} branch indexes 146 */ 147 treeItemBranchIndexes: function(parent, index) { 148 var children = this.get('treeItemChildren'), 149 ret, lim, idx, item; 150 151 if (!children) return null ; // nothing to do 152 153 ret = SC.IndexSet.create(); 154 lim = children.get('length'); 155 for(idx=0;idx<lim;idx++) { 156 if (!(item = children.objectAt(idx))) continue; 157 if (!item.get('treeItemChildren')) continue; 158 if (item.treeItemDisclosureState(this,idx)!==SC.LEAF_NODE) ret.add(idx); 159 } 160 161 return ret.get('length')>0 ? ret : null; 162 } 163 164 }; 165