1 /**
  2  * @fileOverview common render for node
  3  * @author yiminghe@gmail.com
  4  */
  5 KISSY.add("tree/basenodeRender", function (S, Node, Component, DOM) {
  6     var $ = Node.all,
  7         LABEL_CLS = "ks-tree-item-content",
  8         FILE_CLS = "ks-tree-file-icon",
  9         FILE_EXPAND = "ks-tree-expand-icon-{t}",
 10         FOLDER_EXPAND = FILE_EXPAND + "minus",
 11         FOLDER_COLLAPSED = FILE_EXPAND + "plus",
 12         INLINE_BLOCK = " ks-inline-block",
 13         FOLDER_ICON_EXPANDED = "ks-tree-expanded-folder-icon",
 14         FOLDER_ICON_COLLAPSED = "ks-tree-collapsed-folder-icon",
 15         CHILDREN_CLS = "ks-tree-children",
 16         CHILDREN_CLS_L = "ks-tree-lchildren",
 17         EXPAND_ICON_CLS = "ks-tree-expand-icon",
 18         ICON_CLS = "ks-tree-icon",
 19         LEAF_CLS = "tree-item-leaf",
 20         NOT_LEAF_CLS = "ks-tree-item-folder",
 21         ROW_CLS = "ks-tree-item-row";
 22 
 23     return Component.Render.extend({
 24 
 25         _computeClass:function (children, parent) {
 26             var self = this,
 27                 expanded = self.get("expanded"),
 28                 isLeaf = self.get("isLeaf"),
 29                 iconEl = self.get("iconEl"),
 30                 expandIconEl = self.get("expandIconEl"),
 31                 childrenEl = self.get("childrenEl"),
 32                 expand_cls = [ICON_CLS, EXPAND_ICON_CLS, ""].join(" "),
 33                 icon_cls = [ICON_CLS, FILE_CLS, ""].join(" ") + INLINE_BLOCK,
 34                 folder_cls = [ ICON_CLS, expanded ? FOLDER_ICON_EXPANDED :
 35                     FOLDER_ICON_COLLAPSED, ""].join(" ") + INLINE_BLOCK,
 36                 lastChild = parent && parent.get("children")[parent.get("children").length - 1],
 37                 last = !parent || !lastChild || lastChild.get("view") == self;
 38             // 强制指定了 isLeaf,否则根据儿子节点集合自动判断
 39             if (isLeaf === false || (isLeaf === undefined && children.length)) {
 40                 iconEl.attr("class", folder_cls);
 41                 if (expanded) {
 42                     expand_cls += FOLDER_EXPAND;
 43                 } else {
 44                     expand_cls += FOLDER_COLLAPSED;
 45                 }
 46                 expandIconEl.attr("class", S.substitute(expand_cls, {
 47                     t:last ? "l" : "t"
 48                 }) + INLINE_BLOCK);
 49             } else
 50             //if (isLeaf !== false && (isLeaf ==true || !children.length))
 51             {
 52                 iconEl.attr("class", icon_cls);
 53                 expandIconEl.attr("class", S.substitute((expand_cls + FILE_EXPAND), {
 54                     t:last ? "l" : "t"
 55                 }) + INLINE_BLOCK);
 56             }
 57             childrenEl && childrenEl.attr("class", (last ? CHILDREN_CLS_L : CHILDREN_CLS));
 58 
 59         },
 60 
 61         createDom:function () {
 62             var self = this,
 63                 el = self.get("el"),
 64                 id,
 65                 rowEl,
 66                 contentEl = self.get("contentEl");
 67 
 68             rowEl = $("<div class='" + ROW_CLS + "'/>");
 69 
 70             id = S.guid('tree-item');
 71 
 72             self.__set("rowEl", rowEl);
 73 
 74             var expandIconEl = $("<div/>")
 75                 .appendTo(rowEl);
 76 
 77             var iconEl = $("<div />")
 78                 .appendTo(rowEl);
 79 
 80             contentEl.appendTo(rowEl);
 81 
 82             el.attr({
 83                 role:"treeitem",
 84                 aria-labelledby:id
 85             }).prepend(rowEl);
 86 
 87             self.__set("expandIconEl", expandIconEl);
 88             self.__set("iconEl", iconEl);
 89 
 90         },
 91 
 92         _uiSetExpanded:function (v) {
 93             var self = this,
 94                 childrenEl = self.get("childrenEl");
 95             if (childrenEl) {
 96                 if (!v) {
 97                     childrenEl.hide();
 98                 } else if (v) {
 99                     childrenEl.show();
100                 }
101             }
102             self.get("el").attr("aria-expanded", v);
103         },
104 
105         _uiSetSelected:function (v) {
106             var self = this,
107                 classes = self.getComponentCssClassWithState("-selected"),
108             // selected 放在 row 上,防止由于子选择器而干扰节点的子节点显示
109             // .selected .label {background:xx;}
110                 rowEl = self.get("rowEl");
111             rowEl[v ? "addClass" : "removeClass"](classes);
112             self.get("el").attr("aria-selected", v);
113         },
114 
115         _uiSetDepth:function (v) {
116             this.get("el").attr("aria-level", v);
117         },
118 
119         _uiSetAriaSize:function (v) {
120             this.get("el").attr("aria-setsize", v);
121         },
122 
123         _uiSetAriaPosInSet:function (v) {
124             this.get("el").attr("aria-posinset", v);
125         },
126 
127         _uiSetTooltip:function (v) {
128             this.get("el").attr("title", v);
129         },
130 
131         /**
132          * 内容容器节点,子树节点都插到这里
133          * 默认调用 Component.Render.prototype.getContentElement 为当前节点的容器
134          * 而对于子树节点,它有自己的子树节点容器(单独的div),而不是儿子都直接放在自己的容器里面
135          * @protected
136          * @return {NodeList}
137          */
138         getContentElement:function () {
139             var self = this;
140             if (self.get("childrenEl")) {
141                 return self.get("childrenEl");
142             }
143             var c = $("<div " + (self.get("expanded") ? "" : "style='display:none'")
144                 + " role='group'><" + "/div>")
145                 .appendTo(self.get("el"));
146             self.__set("childrenEl", c);
147             return c;
148         }
149     }, {
150         ATTRS:{
151             ariaSize:{},
152             ariaPosInSet:{},
153             childrenEl:{},
154             expandIconEl:{},
155             tooltip:{},
156             iconEl:{},
157             expanded:{
158                 value:false
159             },
160             rowEl:{},
161             depth:{
162                 value:0
163             },
164             contentEl:{
165                 valueFn:function () {
166                     return $("<span id='" + S.guid("tree-item") + "' class='" + LABEL_CLS + "'/>");
167                 }
168             },
169             isLeaf:{},
170             selected:{}
171         },
172 
173         HTML_PARSER:{
174             childrenEl:function (el) {
175                 return el.children("." + CHILDREN_CLS);
176             },
177             contentEl:function (el) {
178                 return el.children("." + LABEL_CLS);
179             },
180             isLeaf:function (el) {
181                 var self = this;
182                 if (el.hasClass(self.getCssClassWithPrefix(LEAF_CLS))) {
183                     return true;
184                 }
185                 if (el.hasClass(self.getCssClassWithPrefix(NOT_LEAF_CLS))) {
186                     return false;
187                 }
188             },
189             expanded:function (el) {
190                 var children = el.one("." + "ks-tree-children");
191                 if (!children) {
192                     return false;
193                 }
194                 return children.css("display") != "none";
195             }
196         }
197 
198     });
199 
200 }, {
201     requires:['node', 'component', 'dom']
202 });