1 /** 2 * @fileOverview checkable tree node 3 * @author yiminghe@gmail.com 4 */ 5 KISSY.add("tree/checknode", function (S, Node, BaseNode, CheckNodeRender) { 6 var $ = Node.all, 7 PARTIAL_CHECK = 2, 8 CHECK = 1, 9 EMPTY = 0; 10 11 /** 12 * @name CheckNode 13 * @memberOf Tree 14 * @class 15 * Checked tree node. 16 * xclass: 'tree-check-item'. 17 * @extends Tree.Node 18 */ 19 var CheckNode = BaseNode.extend( 20 /** 21 * @lends Tree.CheckNode# 22 */ 23 { 24 25 /** 26 * See {@link Tree.Node#expandAll} 27 */ 28 expandAll:function () { 29 return CheckNode.superclass.expandAll.apply(this, arguments); 30 }, 31 32 performActionInternal:function (e) { 33 var self = this; 34 // 需要通知 tree 获得焦点 35 self.get("tree").get("el")[0].focus(); 36 var target = $(e.target), 37 view = self.get("view"), 38 tree = self.get("tree"); 39 40 if (e.type == "dblclick") { 41 // 双击在 +- 号上无效 42 if (target.equals(view.get("expandIconEl"))) { 43 return; 44 } 45 // 双击在 checkbox 上无效 46 if (target.equals(view.get("checkEl"))) { 47 return; 48 } 49 // 双击在字或者图标上,切换 expand 装tai 50 self.set("expanded", !self.get("expanded")); 51 } 52 53 // 点击在 +- 号,切换状态 54 if (target.equals(view.get("expandIconEl"))) { 55 self.set("expanded", !self.get("expanded")); 56 return; 57 } 58 59 // 单击任何其他地方都切换 check 状态 60 var checkState = self.get("checkState"); 61 if (checkState == CHECK) { 62 checkState = EMPTY; 63 } else { 64 checkState = CHECK; 65 } 66 self.set("checkState", checkState); 67 tree.fire("click", { 68 target:self 69 }); 70 }, 71 72 _uiSetCheckState:function (s) { 73 var self = this; 74 if (s == CHECK || s == EMPTY) { 75 S.each(self.get("children"), function (c) { 76 c.set("checkState", s); 77 }); 78 } 79 // 每次状态变化都通知 parent 沿链检查,一层层向上通知 80 // 效率不高,但是结构清晰 81 var parent = self.get("parent"); 82 if (parent) { 83 var checkCount = 0; 84 var cs = parent.get("children"); 85 for (var i = 0; i < cs.length; i++) { 86 var c = cs[i], cState = c.get("checkState"); 87 // 一个是部分选,父亲必定是部分选,立即结束 88 if (cState == PARTIAL_CHECK) { 89 parent.set("checkState", PARTIAL_CHECK); 90 return; 91 } else if (cState == CHECK) { 92 checkCount++; 93 } 94 } 95 96 // 儿子全都选了,父亲也全选 97 if (checkCount == cs.length) { 98 parent.set("checkState", CHECK); 99 } 100 // 儿子都没选,父亲也不选 101 else if (checkCount === 0) { 102 parent.set("checkState", EMPTY); 103 } 104 // 有的儿子选了,有的没选,父亲部分选 105 else { 106 parent.set("checkState", PARTIAL_CHECK); 107 } 108 } 109 } 110 }, { 111 ATTRS:/** 112 * @lends Tree.CheckNode# 113 */ 114 { 115 116 /** 117 * Enums for check states. 118 * CheckNode.PARTIAL_CHECK: checked partly. 119 * CheckNode.CHECK: checked completely. 120 * CheckNode.EMPTY: not checked. 121 * @type Number 122 */ 123 checkState:{ 124 view:1 125 }, 126 127 xrender:{ 128 value:CheckNodeRender 129 } 130 } 131 }, { 132 xclass:"tree-check-item", 133 priority:20 134 }); 135 136 S.mix(CheckNode, 137 /** 138 * @lends Tree.CheckNode 139 */ 140 { 141 /** 142 * checked partly. 143 */ 144 PARTIAL_CHECK:PARTIAL_CHECK, 145 /** 146 * checked completely. 147 */ 148 CHECK:CHECK, 149 /** 150 * not checked at all. 151 */ 152 EMPTY:EMPTY 153 }) 154 155 return CheckNode; 156 }, { 157 requires:['node', './basenode', './checknodeRender'] 158 });