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 });