1 /**
  2  * @fileOverview droppable for kissy
  3  * @author yiminghe@gmail.com
  4  */
  5 KISSY.add("dd/droppable", function (S, Node, Base, DDM) {
  6 
  7     var PREFIX_CLS = DDM.PREFIX_CLS;
  8 
  9     /**
 10      * @name Droppable
 11      * @memberOf DD
 12      * @class
 13      * Make a node droppable.
 14      */
 15     function Droppable() {
 16         var self = this;
 17         Droppable.superclass.constructor.apply(self, arguments);
 18         self.addTarget(DDM);
 19         S.each([
 20         /**
 21          * @name DD.DDM#dropexit
 22          * @description fired after a draggable leaves a droppable
 23          * @event
 24          * @param e
 25          * @param e.drag current draggable object
 26          * @param e.drop current droppable object
 27          */
 28 
 29         /**
 30          * @name DD.Droppable#dropexit
 31          * @description fired after a draggable leaves a droppable
 32          * @event
 33          * @param e
 34          * @param e.drag current draggable object
 35          * @param e.drop current droppable object
 36          */
 37             "dropexit",
 38 
 39         /**
 40          * @name DD.DDM#dropenter
 41          * @description fired after a draggable object mouseenter a droppable object
 42          * @event
 43          * @param e
 44          * @param e.drag current draggable object
 45          * @param e.drop current droppable object
 46          */
 47 
 48         /**
 49          * @name DD.Droppable#dropenter
 50          * @description fired after a draggable object mouseenter a droppable object
 51          * @event
 52          * @param e
 53          * @param e.drag current draggable object
 54          * @param e.drop current droppable object
 55          */
 56 
 57             "dropenter",
 58 
 59         /**
 60          * @name DD.DDM#dropover
 61          * @description fired after a draggable object mouseover a droppable object
 62          * @event
 63          * @param e
 64          * @param e.drag current draggable object
 65          * @param e.drop current droppable object
 66          */
 67 
 68         /**
 69          * @name DD.Droppable#dropover
 70          * @description fired after a draggable object mouseover a droppable object
 71          * @event
 72          * @param e
 73          * @param e.drag current draggable object
 74          * @param e.drop current droppable object
 75          */
 76             "dropover",
 77 
 78         /**
 79          * @name DD.DDM#drophit
 80          * @description fired after drop a draggable onto a droppable object
 81          * @event
 82          * @param e
 83          * @param e.drag current draggable object
 84          * @param e.drop current droppable object
 85          */
 86 
 87         /**
 88          * @name DD.Droppable#drophit
 89          * @description fired after drop a draggable onto a droppable object
 90          * @event
 91          * @param e
 92          * @param e.drag current draggable object
 93          * @param e.drop current droppable object
 94          */
 95             "drophit"
 96         ], function (e) {
 97             self.publish(e, {
 98                 bubbles:1
 99             });
100         });
101         self._init();
102     }
103 
104     Droppable.ATTRS =
105     /**
106      * @lends DD.Droppable#
107      */
108     {
109         /**
110          * droppable element
111          * @type String|HTMLElement
112          */
113         node:{
114             setter:function (v) {
115                 if (v) {
116                     return Node.one(v);
117                 }
118             }
119         },
120 
121         /**
122          * groups this droppable object belongs to. Default:true
123          * @type Object|Boolean true to match any group
124          */
125         groups:{
126             value:true
127         }
128 
129     };
130 
131     function validDrop(dropGroups, dragGroups) {
132         if (dropGroups === true) {
133             return 1;
134         }
135         for (var d in dropGroups) {
136             if (dragGroups[d]) {
137                 return 1;
138             }
139         }
140         return 0;
141     }
142 
143     S.extend(Droppable, Base,
144         /**
145          * @lends DD.Droppable#
146          */
147         {
148             /**
149              * override by droppable-delegate override
150              * @private
151              */
152             getNodeFromTarget:function (ev, dragNode, proxyNode) {
153                 var node = this.get("node"),
154                     domNode = node[0];
155                 // 排除当前拖放和代理节点
156                 return domNode == dragNode ||
157                     domNode == proxyNode
158                     ? null : node;
159             },
160 
161             _init:function () {
162                 DDM._regDrop(this);
163             },
164 
165             _active:function () {
166                 var self = this,
167                     drag = DDM.get("activeDrag"),
168                     node = self.get("node"),
169                     dropGroups = self.get("groups"),
170                     dragGroups = drag.get("groups");
171                 if (validDrop(dropGroups, dragGroups)) {
172                     DDM._addValidDrop(self);
173                     // 委托时取不到节点
174                     if (node) {
175                         node.addClass(PREFIX_CLS + "drop-active-valid");
176                         DDM.cacheWH(node);
177                     }
178                 } else if (node) {
179                     node.addClass(PREFIX_CLS + "drop-active-invalid");
180                 }
181             },
182 
183             _deActive:function () {
184                 var node = this.get("node");
185                 if (node) {
186                     node.removeClass(PREFIX_CLS + "drop-active-valid")
187                         .removeClass(PREFIX_CLS + "drop-active-invalid");
188                 }
189             },
190 
191             __getCustomEvt:function (ev) {
192                 return S.mix({
193                     drag:DDM.get("activeDrag"),
194                     drop:this
195                 }, ev);
196             },
197 
198             _handleOut:function () {
199                 var self = this,
200                     ret = self.__getCustomEvt();
201                 self.get("node").removeClass(PREFIX_CLS + "drop-over");
202                 /**
203                  * html5 => dragleave
204                  */
205                 self.fire("dropexit", ret);
206             },
207 
208             _handleEnter:function (ev) {
209                 var self = this,
210                     e = self.__getCustomEvt(ev);
211                 e.drag._handleEnter(e);
212                 self.get("node").addClass(PREFIX_CLS + "drop-over");
213                 self.fire("dropenter", e);
214             },
215 
216 
217             _handleOver:function (ev) {
218                 var self = this,
219                     e = self.__getCustomEvt(ev);
220                 e.drag._handleOver(e);
221                 self.fire("dropover", e);
222             },
223 
224             _end:function () {
225                 var self = this,
226                     ret = self.__getCustomEvt();
227                 self.get("node").removeClass(PREFIX_CLS + "drop-over");
228                 self.fire('drophit', ret);
229             },
230 
231             /**
232              * make this droppable' element undroppable
233              */
234             destroy:function () {
235                 DDM._unRegDrop(this);
236             }
237         });
238 
239     return Droppable;
240 
241 }, { requires:["node", "base", "./ddm"] });