1 /**
  2  * @fileOverview only one droppable instance for multiple droppable nodes
  3  * @author yiminghe@gmail.com
  4  */
  5 KISSY.add("dd/droppable-delegate", function (S, DDM, Droppable, DOM, Node) {
  6 
  7 
  8     function dragStart() {
  9         var self = this,
 10             container = self.get("container"),
 11             allNodes = [],
 12             selector = self.get("selector");
 13         container.all(selector).each(function (n) {
 14             // 2012-05-18: 缓存高宽,提高性能
 15             DDM.cacheWH(n);
 16             allNodes.push(n);
 17         })
 18         self.__allNodes = allNodes;
 19     }
 20 
 21     /**
 22      * @name DroppableDelegate
 23      * @memberOf DD
 24      * @extends DD.Droppable
 25      * @class
 26      * make multiple nodes droppable under a container using only one droppable instance
 27      */
 28     function DroppableDelegate() {
 29         var self = this;
 30         DroppableDelegate.superclass.constructor.apply(self, arguments);
 31         // 提高性能,拖放开始时缓存代理节点
 32         DDM.on("dragstart", dragStart, self);
 33     }
 34 
 35     S.extend(DroppableDelegate, Droppable,
 36         /**
 37          * @lends DD.DroppableDelegate
 38          */
 39         {
 40 
 41             /**
 42              * Destroy current instance
 43              */
 44             destroy:function(){
 45                 DroppableDelegate.superclass.destroy.apply(this,arguments);
 46             },
 47 
 48             /**
 49              * 根据鼠标位置得到真正的可放目标,暂时不考虑 mode,只考虑鼠标
 50              * @param ev
 51              * @private
 52              * @override
 53              */
 54             getNodeFromTarget:function (ev, dragNode, proxyNode) {
 55                 var pointer = {
 56                         left:ev.pageX,
 57                         top:ev.pageY
 58                     },
 59                     self = this,
 60                     allNodes = self.__allNodes,
 61                     ret = 0,
 62                     vArea = Number.MAX_VALUE;
 63 
 64 
 65                 if (allNodes) {
 66 
 67                     S.each(allNodes, function (n) {
 68                         var domNode = n[0];
 69                         // 排除当前拖放的元素以及代理节点
 70                         if (domNode === proxyNode || domNode === dragNode) {
 71                             return;
 72                         }
 73                         var r = DDM.region(n);
 74                         if (DDM.inRegion(r, pointer)) {
 75                             // 找到面积最小的那个
 76                             var a = DDM.area(r);
 77                             if (a < vArea) {
 78                                 vArea = a;
 79                                 ret = n;
 80                             }
 81                         }
 82                     });
 83                 }
 84 
 85                 if (ret) {
 86                     self.__set("lastNode", self.get("node"));
 87                     self.__set("node", ret);
 88                 }
 89 
 90                 return ret;
 91             },
 92 
 93             _handleOut:function () {
 94                 var self = this;
 95                 DroppableDelegate.superclass._handleOut.apply(self, arguments);
 96                 self.__set("node", 0);
 97                 self.__set("lastNode", 0);
 98             },
 99 
100             _handleOver:function (ev) {
101                 var self = this,
102                     node = self.get("node"),
103                     superOut = DroppableDelegate.superclass._handleOut,
104                     superOver = DroppableDelegate.superclass._handleOver,
105                     superEnter = DroppableDelegate.superclass._handleEnter,
106                     lastNode = self.get("lastNode");
107 
108                 if (lastNode[0] !== node[0]) {
109                     /**
110                      * 同一个 drop 对象内委托的两个可 drop 节点相邻,先通知上次的离开
111                      */
112                     self.__set("node", lastNode);
113                     superOut.apply(self, arguments);
114                     /**
115                      * 再通知这次的进入
116                      */
117                     self.__set("node", node);
118                     superEnter.call(self, ev);
119                 } else {
120                     superOver.call(self, ev);
121                 }
122             },
123 
124             _end:function () {
125                 var self = this;
126                 DroppableDelegate.superclass._end.apply(self, arguments);
127                 self.__set("node", 0);
128             }
129         },
130         {
131             ATTRS:/**
132              * @lends DD.DroppableDelegate#
133              */
134             {
135 
136 
137                 // 继承自 Drappable ,当前正在委托的放节点目标
138 
139 
140                 /**
141                  * 上一个成为放目标的委托节点
142                  * @private
143                  */
144                 lastNode:{
145                 },
146 
147                 /**
148                  * a selector query to get the children of container to make droppable elements from.
149                  * usually as for tag.cls.
150                  * @type String
151                  */
152                 selector:{
153                 },
154 
155                 /**
156                  * a selector query to get the container to listen for mousedown events on.
157                  * All "draggable selector" should be a child of this container
158                  * @type {String|HTMLElement}
159                  */
160                 container:{
161                     setter:function (v) {
162                         return Node.one(v);
163                     }
164                 }
165             }
166         });
167 
168     return DroppableDelegate;
169 }, {
170     requires:['./ddm', './droppable', 'dom', 'node']
171 });