/loggerhead/trunk

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/loggerhead/trunk

« back to all changes in this revision

Viewing changes to loggerhead/static/javascript/yui/build/dd/dd-constrain-debug.js

  • Committer: Colin Watson
  • Date: 2020-06-08 09:55:03 UTC
  • mfrom: (498.2.2 jquery)
  • Revision ID: cjwatson@canonical.com-20200608095503-n387xggxud2khqsw
[r=cjwatson] Port loggerhead from YUI to jQuery.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
3
 
Code licensed under the BSD License:
4
 
http://developer.yahoo.net/yui/license.txt
5
 
version: 3.0.0pr2
6
 
*/
7
 
YUI.add('dd-constrain', function(Y) {
8
 
 
9
 
    /**
10
 
     * The Drag & Drop Utility allows you to create a draggable interface efficiently, buffering you from browser-level abnormalities and enabling you to focus on the interesting logic surrounding your particular implementation. This component enables you to create a variety of standard draggable objects with just a few lines of code and then, using its extensive API, add your own specific implementation logic.
11
 
     * @module dd
12
 
     * @submodule dd-constrain
13
 
     */
14
 
    /**
15
 
     * This class extends the dd-drag module to add the constraining methods to it. It supports constraining to a region, node or viewport. It also
16
 
     * supports tick based moves and XY axis constraints.
17
 
     * @class DragConstrained
18
 
     * @extends Drag
19
 
     * @constructor
20
 
     */
21
 
 
22
 
    var DRAG_NODE = 'dragNode',
23
 
        OFFSET_HEIGHT = 'offsetHeight',
24
 
        OFFSET_WIDTH = 'offsetWidth';
25
 
 
26
 
 
27
 
    var C = function() {
28
 
        C.superclass.constructor.apply(this, arguments);
29
 
 
30
 
    };
31
 
    
32
 
    C.NAME = 'dragConstrained';
33
 
 
34
 
    C.ATTRS = {
35
 
        /**
36
 
        * @attribute stickX
37
 
        * @description Stick the drag movement to the X-Axis. Default: false
38
 
        * @type Boolean
39
 
        */        
40
 
        stickX: {
41
 
            value: false
42
 
        },
43
 
        /**
44
 
        * @attribute stickY
45
 
        * @description Stick the drag movement to the Y-Axis
46
 
        * @type Boolean
47
 
        */        
48
 
        stickY: {
49
 
            value: false
50
 
        },
51
 
        /**
52
 
        * @attribute tickX
53
 
        * @description The X tick offset the drag node should snap to on each drag move. False for no ticks. Default: false
54
 
        * @type Number/false
55
 
        */        
56
 
        tickX: {
57
 
            value: false
58
 
        },
59
 
        /**
60
 
        * @attribute tickY
61
 
        * @description The Y tick offset the drag node should snap to on each drag move. False for no ticks. Default: false
62
 
        * @type Number/false
63
 
        */        
64
 
        tickY: {
65
 
            value: false
66
 
        },
67
 
        /**
68
 
        * @attribute tickXArray
69
 
        * @description An array of page coordinates to use as X ticks for drag movement.
70
 
        * @type Array
71
 
        */
72
 
        tickXArray: {
73
 
            value: false
74
 
        },
75
 
        /**
76
 
        * @attribute tickYArray
77
 
        * @description An array of page coordinates to use as Y ticks for drag movement.
78
 
        * @type Array
79
 
        */
80
 
        tickYArray: {
81
 
            value: false
82
 
        },
83
 
        /**
84
 
        * @attribute constrain2region
85
 
        * @description An Object Literal containing a valid region (top, right, bottom, left) of page positions to constrain the drag node to.
86
 
        * @type Object
87
 
        */
88
 
        constrain2region: {
89
 
            value: false,
90
 
            get: function(r) {
91
 
                if (Y.Lang.isObject(r)) {
92
 
                    var o = {};
93
 
                    Y.mix(o, r);
94
 
                    return o;
95
 
                } else {
96
 
                    return false;
97
 
                }
98
 
            },
99
 
            set: function (r) {
100
 
                if (Y.Lang.isObject(r)) {
101
 
                    if (r.top && r.right && r.left && r.bottom) {
102
 
                        var o = {};
103
 
                        Y.mix(o, r);
104
 
                        return o;
105
 
                    } else {
106
 
                        Y.log('constrain2region expecting a valid object with (top, right, bottom, left properties)', 'error', 'DragConstrain');
107
 
                        return false;
108
 
                    }
109
 
                } else if (r !== false) {
110
 
                    Y.log('constrain2region expecting an object', 'error', 'DragConstrain');
111
 
                    return false;
112
 
                }
113
 
            }
114
 
        },
115
 
        /**
116
 
        * @attribute gutter
117
 
        * @description CSS style string for the gutter of a region (supports negative values): '5 0' (sets top and bottom to 5px, left and right to 0px), '1 2 3 4' (top 1px, right 2px, bottom 3px, left 4px)        
118
 
        * @type String
119
 
        */
120
 
        gutter: {
121
 
            value: '0',
122
 
            set: function(gutter) {
123
 
                return Y.DD.DDM.cssSizestoObject(gutter);
124
 
            }
125
 
        },
126
 
        /**
127
 
        * @attribute constrain2node
128
 
        * @description Will attempt to constrain the drag node to the bounderies of this node.
129
 
        * @type Object
130
 
        */
131
 
        constrain2node: {
132
 
            value: false,
133
 
            set: function(n) {
134
 
                if (!this.get('constrain2region')) {
135
 
                    var node = Y.Node.get(n);
136
 
                    if (node) {
137
 
                        return node;
138
 
                    }
139
 
                } else if (this.get('constrain2region') !== false) {
140
 
                    Y.log('constrain2region found, can not have both. Node ignored', 'warn', 'DragConstrain');
141
 
                }
142
 
                return false;
143
 
            }
144
 
        },
145
 
        /**
146
 
        * @attribute constrain2view
147
 
        * @description Will attempt to constrain the drag node to the bounderies of the viewport region.
148
 
        * @type Object
149
 
        */
150
 
        constrain2view: {
151
 
            value: false
152
 
        }
153
 
    };
154
 
 
155
 
    var proto = {
156
 
        start: function() {
157
 
            C.superclass.start.apply(this, arguments);
158
 
            this._regionCache = null;
159
 
        },
160
 
        /**
161
 
        * @private
162
 
        * @property _regionCache
163
 
        * @description Store a cache of the region that we are constraining to
164
 
        * @type Object
165
 
        */
166
 
        _regionCache: null,
167
 
        /**
168
 
        * @private
169
 
        * @method _cacheRegion
170
 
        * @description Get's the region and caches it, called from window.resize and when the cache is null
171
 
        */
172
 
        _cacheRegion: function() {
173
 
            this._regionCache = this.get('constrain2node').get('region');
174
 
        },
175
 
        /**
176
 
        * @method getRegion
177
 
        * @description Get the active region: viewport, node, custom region
178
 
        * @param {Boolean} inc Include the node's height and width
179
 
        * @return {Object}
180
 
        */
181
 
        getRegion: function(inc) {
182
 
            var r = {};
183
 
            if (this.get('constrain2node')) {
184
 
                if (!this._regionCache) {
185
 
                    Y.on('resize', this._cacheRegion, this, true, window);
186
 
                    this._cacheRegion();
187
 
                }
188
 
                r = Y.clone(this._regionCache);
189
 
            } else if (this.get('constrain2region')) {
190
 
                r = this.get('constrain2region');
191
 
            } else if (this.get('constrain2view')) {
192
 
                r = this.get('node').get('viewportRegion');
193
 
            } else {
194
 
                return false;
195
 
            }
196
 
            var g = this.get('gutter');
197
 
            Y.each(g, function(i, n) {
198
 
                if ((n == 'right') || (n == 'bottom')) {
199
 
                    r[n] -= i;
200
 
                } else {
201
 
                    r[n] += i;
202
 
                }
203
 
            });
204
 
            if (inc) {
205
 
                var oh = this.get(DRAG_NODE).get(OFFSET_HEIGHT),
206
 
                    ow = this.get(DRAG_NODE).get(OFFSET_WIDTH);
207
 
                r.right = r.right - ow;
208
 
                r.bottom = r.bottom - oh;
209
 
            }
210
 
            return r;
211
 
        },
212
 
        /**
213
 
        * @private
214
 
        * @method _checkRegion
215
 
        * @description
216
 
        * @param {Array} _xy The XY to check if it's in the current region, if it isn't inside the region, it will reset the xy array to be inside the region.
217
 
        * @return {Array} The new XY that is inside the region
218
 
        */
219
 
        _checkRegion: function(_xy) {
220
 
            var oxy = _xy,
221
 
                r = this.getRegion(),
222
 
                oh = this.get(DRAG_NODE).get(OFFSET_HEIGHT),
223
 
                ow = this.get(DRAG_NODE).get(OFFSET_WIDTH);
224
 
            
225
 
                if (oxy[1] > (r.bottom - oh)) {
226
 
                    _xy[1] = (r.bottom - oh);
227
 
                }
228
 
                if (r.top > oxy[1]) {
229
 
                    _xy[1] = r.top;
230
 
 
231
 
                }
232
 
                if (oxy[0] > (r.right - ow)) {
233
 
                    _xy[0] = (r.right - ow);
234
 
                }
235
 
                if (r.left > oxy[0]) {
236
 
                    _xy[0] = r.left;
237
 
                }
238
 
 
239
 
            return _xy;
240
 
        },
241
 
        /**
242
 
        * @method inRegion
243
 
        * @description Checks if the XY passed or the dragNode is inside the active region.
244
 
        * @param {Array} xy Optional XY to check, if not supplied this.get('dragNode').getXY() is used.
245
 
        * @return {Boolean} True if the XY is inside the region, false otherwise.
246
 
        */
247
 
        inRegion: function(xy) {
248
 
            xy = xy || this.get(DRAG_NODE).getXY();
249
 
 
250
 
            var _xy = this._checkRegion([xy[0], xy[1]]),
251
 
                inside = false;
252
 
                if ((xy[0] === _xy[0]) && (xy[1] === _xy[1])) {
253
 
                    inside = true;
254
 
                }
255
 
            return inside;
256
 
        },
257
 
        /**
258
 
        * @private
259
 
        * @method _align
260
 
        * @description Override of Drag _align to account for region checking and tick checking
261
 
        * @param {Array} xy The XY to check for ticks and region
262
 
        * @return {Array} The modified XY coords.
263
 
        */
264
 
        _align: function(xy) {
265
 
            var _xy = C.superclass._align.apply(this, arguments),
266
 
                r = this.getRegion(true);
267
 
 
268
 
            if (this.get('stickX')) {
269
 
                _xy[1] = (this.startXY[1] - this.deltaXY[1]);
270
 
            }
271
 
            if (this.get('stickY')) {
272
 
                _xy[0] = (this.startXY[0] - this.deltaXY[0]);
273
 
            }
274
 
 
275
 
 
276
 
            if (r) {
277
 
                _xy = this._checkRegion(_xy);
278
 
            }
279
 
                
280
 
            _xy = this._checkTicks(_xy, r);
281
 
            return _xy;
282
 
        },
283
 
        /**
284
 
        * @private
285
 
        * @method _calcTicks
286
 
        * @description Helper method to calculate the tick offsets for a given position
287
 
        * @param {Number} pos The current X or Y position
288
 
        * @param {Number} start The start X or Y position
289
 
        * @param {Number} tick The X or Y tick increment
290
 
        * @param {Number} off1 The min offset that we can't pass (region)
291
 
        * @param {Number} off2 The max offset that we can't pass (region)
292
 
        * @return {Number} The new position based on the tick calculation
293
 
        */
294
 
        _calcTicks: function(pos, start, tick, off1, off2) {
295
 
            var ix = ((pos - start) / tick),
296
 
                min = Math.floor(ix),
297
 
                max = Math.ceil(ix);
298
 
                if ((min !== 0) || (max !== 0)) {
299
 
                    if ((ix >= min) && (ix <= max)) {
300
 
                        pos = (start + (tick * min));
301
 
                        if (off1 && off2) {
302
 
                            if (pos < off1) {
303
 
                                pos = (start + (tick * (min + 1)));
304
 
                            }
305
 
                            if (pos > off2) {
306
 
                                pos = (start + (tick * (min - 1)));
307
 
                            }
308
 
                        }
309
 
                    }
310
 
                }
311
 
                return pos;
312
 
        },
313
 
        /**
314
 
        * @private
315
 
        * @method _calcTickArray
316
 
        * @description This method is used with the tickXArray and tickYArray config options
317
 
        * @param {Number} pos The current X or Y position
318
 
        * @param {Number} ticks The array containing our custom tick positions.
319
 
        * @param {Number} off1 The min offset that we can't pass (region)
320
 
        * @param {Number} off2 The max offset that we can't pass (region)
321
 
        * @return The tick position
322
 
        */
323
 
        _calcTickArray: function(pos, ticks, off1, off2) {
324
 
            var i = 0, len = ticks.length, next = 0;
325
 
 
326
 
            if (!ticks || (ticks.length === 0)) {
327
 
                return pos;
328
 
            } else if (ticks[0] >= pos) {
329
 
                return ticks[0];
330
 
            } else {
331
 
                for (i = 0; i < len; i++) {
332
 
                    next = (i + 1);
333
 
                    if (ticks[next] && ticks[next] >= pos) {
334
 
                        var diff1 = pos - ticks[i],
335
 
                            diff2 = ticks[next] - pos;
336
 
                        var ret = (diff2 > diff1) ? ticks[i] : ticks[next];
337
 
                        if (off1 && off2) {
338
 
                            if (ret > off2) {
339
 
                                if (ticks[i]) {
340
 
                                    ret = ticks[i];
341
 
                                } else {
342
 
                                    ret = ticks[len - 1];
343
 
                                }
344
 
                            }
345
 
                        }
346
 
                        return ret;
347
 
                    }
348
 
                    
349
 
                }
350
 
                return ticks[ticks.length - 1];
351
 
            }
352
 
        },
353
 
        /**
354
 
        * @private
355
 
        * @method _checkTicks
356
 
        * @description This method delegates the proper helper method for tick calculations
357
 
        * @param {Array} xy The XY coords for the Drag
358
 
        * @param {Object} r The optional region that we are bound to.
359
 
        * @return {Array} The calced XY coords
360
 
        */
361
 
        _checkTicks: function(xy, r) {
362
 
            var lx = (this.startXY[0] - this.deltaXY[0]),
363
 
                ly = (this.startXY[1] - this.deltaXY[1]),
364
 
                xt = this.get('tickX'),
365
 
                yt = this.get('tickY');
366
 
                if (xt && !this.get('tickXArray')) {
367
 
                    xy[0] = this._calcTicks(xy[0], lx, xt, r.left, r.right);
368
 
                }
369
 
                if (yt && !this.get('tickYArray')) {
370
 
                    xy[1] = this._calcTicks(xy[1], ly, yt, r.top, r.bottom);
371
 
                }
372
 
                if (this.get('tickXArray')) {
373
 
                    xy[0] = this._calcTickArray(xy[0], this.get('tickXArray'), r.left, r.right);
374
 
                }
375
 
                if (this.get('tickYArray')) {
376
 
                    xy[1] = this._calcTickArray(xy[1], this.get('tickYArray'), r.top, r.bottom);
377
 
                }
378
 
 
379
 
            return xy;
380
 
        }
381
 
    };
382
 
    //Extend DD.Drag
383
 
    Y.extend(C, Y.DD.Drag, proto);
384
 
    //Set this to DD.Drag for other extensions
385
 
    Y.DD.Drag = C;
386
 
 
387
 
 
388
 
 
389
 
}, '3.0.0pr2' ,{requires:['dd-drag', 'dd-proxy'], skinnable:false});