MDL-32843 import YUI 3.5.1
[moodle.git] / lib / yui / 3.5.1 / build / dd-delegate / dd-delegate.js
blobbc95adf298ae9b64e07138b2c950a169c0025005
1 /*
2 YUI 3.5.1 (build 22)
3 Copyright 2012 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
6 */
7 YUI.add('dd-delegate', function(Y) {
10     /**
11      * Provides the ability to drag multiple nodes under a container element using only one Y.DD.Drag instance as a delegate.
12      * @module dd
13      * @submodule dd-delegate
14      */     
15     /**
16      * Provides the ability to drag multiple nodes under a container element using only one Y.DD.Drag instance as a delegate.
17      * @class Delegate
18      * @extends Base
19      * @constructor
20      * @namespace DD
21      */
24     var Delegate = function(o) {
25         Delegate.superclass.constructor.apply(this, arguments);
26     },
27     CONT = 'container',
28     NODES = 'nodes',
29     _tmpNode = Y.Node.create('<div>Temp Node</div>');
32     Y.extend(Delegate, Y.Base, {
33         /**
34         * @private
35         * @property _bubbleTargets
36         * @description The default bubbleTarget for this object. Default: Y.DD.DDM
37         */
38         _bubbleTargets: Y.DD.DDM,
39         /**
40         * @property dd
41         * @description A reference to the temporary dd instance used under the hood.
42         */    
43         dd: null,
44         /**
45         * @property _shimState
46         * @private
47         * @description The state of the Y.DD.DDM._noShim property to it can be reset.
48         */    
49         _shimState: null,
50         /**
51         * @private
52         * @property _handles
53         * @description Array of event handles to be destroyed
54         */
55         _handles: null,
56         /**
57         * @private
58         * @method _onNodeChange
59         * @description Listens to the nodeChange event and sets the dragNode on the temp dd instance.
60         * @param {Event} e The Event.
61         */
62         _onNodeChange: function(e) {
63             this.set('dragNode', e.newVal);
64         },
65         /**
66         * @private
67         * @method _afterDragEnd
68         * @description Listens for the drag:end event and updates the temp dd instance.
69         * @param {Event} e The Event.
70         */
71         _afterDragEnd: function(e) {
72             Y.DD.DDM._noShim = this._shimState;
74             this.set('lastNode', this.dd.get('node'));
75             this.get('lastNode').removeClass(Y.DD.DDM.CSS_PREFIX + '-dragging');
76             this.dd._unprep();
77             this.dd.set('node', _tmpNode);
78         },
79         /**
80         * @private
81         * @method _delMouseDown
82         * @description The callback for the Y.DD.Delegate instance used
83         * @param {Event} e The MouseDown Event.
84         */
85         _delMouseDown: function(e) {
86             var tar = e.currentTarget,
87                 dd = this.dd;
88             
89             if (tar.test(this.get(NODES)) && !tar.test(this.get('invalid'))) {
90                 this._shimState = Y.DD.DDM._noShim;
91                 Y.DD.DDM._noShim = true;
92                 this.set('currentNode', tar);
93                 dd.set('node', tar);
94                 if (dd.proxy) {
95                     dd.set('dragNode', Y.DD.DDM._proxy);
96                 } else {
97                     dd.set('dragNode', tar);
98                 }
99                 dd._prep();
100                 
101                 dd.fire('drag:mouseDown', { ev: e });
102             }
103         },
104         /**
105         * @private
106         * @method _onMouseEnter
107         * @description Sets the target shim state
108         * @param {Event} e The MouseEnter Event
109         */
110         _onMouseEnter: function(e) {
111             this._shimState = Y.DD.DDM._noShim;
112             Y.DD.DDM._noShim = true;
113         },
114         /**
115         * @private
116         * @method _onMouseLeave
117         * @description Resets the target shim state
118         * @param {Event} e The MouseLeave Event
119         */
120         _onMouseLeave: function(e) {
121             Y.DD.DDM._noShim = this._shimState;
122         },
123         initializer: function(cfg) {
124             this._handles = [];
125             //Create a tmp DD instance under the hood.
126             //var conf = Y.clone(this.get('dragConfig') || {}),
127             var conf = this.get('dragConfig') || {},
128                 cont = this.get(CONT);
130             conf.node = _tmpNode.cloneNode(true);
131             conf.bubbleTargets = this;
133             if (this.get('handles')) {
134                 conf.handles = this.get('handles');
135             }
137             this.dd = new Y.DD.Drag(conf);
139             //On end drag, detach the listeners
140             this.dd.after('drag:end', Y.bind(this._afterDragEnd, this));
141             this.dd.on('dragNodeChange', Y.bind(this._onNodeChange, this));
142             this.dd.after('drag:mouseup', function() {
143                 this._unprep();
144             });
146             //Attach the delegate to the container
147             this._handles.push(Y.delegate(Y.DD.Drag.START_EVENT, Y.bind(this._delMouseDown, this), cont, this.get(NODES)));
149             this._handles.push(Y.on('mouseenter', Y.bind(this._onMouseEnter, this), cont));
151             this._handles.push(Y.on('mouseleave', Y.bind(this._onMouseLeave, this), cont));
153             Y.later(50, this, this.syncTargets);
154             Y.DD.DDM.regDelegate(this);
155         },
156         /**
157         * @method syncTargets
158         * @description Applies the Y.Plugin.Drop to all nodes matching the cont + nodes selector query.
159         * @return {Self}
160         * @chainable
161         */        
162         syncTargets: function() {
163             if (!Y.Plugin.Drop || this.get('destroyed')) {
164                 return;
165             }
166             var items, groups, config;
168             if (this.get('target')) {
169                 items = Y.one(this.get(CONT)).all(this.get(NODES));
170                 groups = this.dd.get('groups');
171                 config = this.get('dragConfig');
172                 
173                 if (config && 'groups' in config) {
174                     groups = config.groups;
175                 }
177                 items.each(function(i) {
178                     this.createDrop(i, groups);
179                 }, this);
180             }
181             return this;
182         },
183         /**
184         * @method createDrop
185         * @description Apply the Drop plugin to this node
186         * @param {Node} node The Node to apply the plugin to
187         * @param {Array} groups The default groups to assign this target to.
188         * @return Node
189         */
190         createDrop: function(node, groups) {
191             var config = {
192                 useShim: false,
193                 bubbleTargets: this
194             };
196             if (!node.drop) {
197                 node.plug(Y.Plugin.Drop, config);
198             }
199             node.drop.set('groups', groups);
200             return node;
201         },
202         destructor: function() {
203             if (this.dd) {
204                 this.dd.destroy();
205             }
206             if (Y.Plugin.Drop) {
207                 var targets = Y.one(this.get(CONT)).all(this.get(NODES));
208                 targets.unplug(Y.Plugin.Drop);
209             }
210             Y.each(this._handles, function(v) {
211                 v.detach();
212             });
213         }
214     }, {
215         NAME: 'delegate',
216         ATTRS: {
217             /**
218             * @attribute container
219             * @description A selector query to get the container to listen for mousedown events on. All "nodes" should be a child of this container.
220             * @type String
221             */    
222             container: {
223                 value: 'body'
224             },
225             /**
226             * @attribute nodes
227             * @description A selector query to get the children of the "container" to make draggable elements from.
228             * @type String
229             */        
230             nodes: {
231                 value: '.dd-draggable'
232             },
233             /**
234             * @attribute invalid
235             * @description A selector query to test a node to see if it's an invalid item.
236             * @type String
237             */        
238             invalid: {
239                 value: 'input, select, button, a, textarea'
240             },
241             /**
242             * @attribute lastNode
243             * @description Y.Node instance of the last item dragged.
244             * @type Node
245             */        
246             lastNode: {
247                 value: _tmpNode
248             },
249             /**
250             * @attribute currentNode
251             * @description Y.Node instance of the dd node.
252             * @type Node
253             */        
254             currentNode: {
255                 value: _tmpNode
256             },
257             /**
258             * @attribute dragNode
259             * @description Y.Node instance of the dd dragNode.
260             * @type Node
261             */        
262             dragNode: {
263                 value: _tmpNode
264             },
265             /**
266             * @attribute over
267             * @description Is the mouse currently over the container
268             * @type Boolean
269             */        
270             over: {
271                 value: false
272             },
273             /**
274             * @attribute target
275             * @description Should the items also be a drop target.
276             * @type Boolean
277             */        
278             target: {
279                 value: false
280             },
281             /**
282             * @attribute dragConfig
283             * @description The default config to be used when creating the DD instance.
284             * @type Object
285             */        
286             dragConfig: {
287                 value: null
288             },
289             /**
290             * @attribute handles
291             * @description The handles config option added to the temp DD instance.
292             * @type Array
293             */        
294             handles: {
295                 value: null
296             }
297         }
298     });
300     Y.mix(Y.DD.DDM, {
301         /**
302         * @private
303         * @for DDM
304         * @property _delegates
305         * @description Holder for all Y.DD.Delegate instances
306         * @type Array
307         */
308         _delegates: [],
309         /**
310         * @for DDM
311         * @method regDelegate
312         * @description Register a Delegate with the DDM
313         */
314         regDelegate: function(del) {
315             this._delegates.push(del);
316         },
317         /**
318         * @for DDM
319         * @method getDelegate
320         * @description Get a delegate instance from a container node
321         * @return Y.DD.Delegate
322         */
323         getDelegate: function(node) {
324             var del = null;
325             node = Y.one(node);
326             Y.each(this._delegates, function(v) {
327                 if (node.test(v.get(CONT))) {
328                     del = v;
329                 }
330             }, this);
331             return del;
332         }
333     });
335     Y.namespace('DD');    
336     Y.DD.Delegate = Delegate;
341 }, '3.5.1' ,{skinnable:false, requires:['dd-drag', 'event-mouseenter', 'dd-drop-plugin']});