Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
YUI.add('resize-constrain', function (Y, NAME) {
2
 
3
var Lang = Y.Lang,
4
    isBoolean = Lang.isBoolean,
5
    isNumber = Lang.isNumber,
6
    isString = Lang.isString,
7
    capitalize = Y.Resize.capitalize,
8
 
9
    isNode = function(v) {
10
        return (v instanceof Y.Node);
11
    },
12
 
13
    toNumber = function(num) {
14
        return parseFloat(num) || 0;
15
    },
16
 
17
    BORDER_BOTTOM_WIDTH = 'borderBottomWidth',
18
    BORDER_LEFT_WIDTH = 'borderLeftWidth',
19
    BORDER_RIGHT_WIDTH = 'borderRightWidth',
20
    BORDER_TOP_WIDTH = 'borderTopWidth',
21
    BORDER = 'border',
22
    BOTTOM = 'bottom',
23
    CON = 'con',
24
    CONSTRAIN = 'constrain',
25
    HOST = 'host',
26
    LEFT = 'left',
27
    MAX_HEIGHT = 'maxHeight',
28
    MAX_WIDTH = 'maxWidth',
29
    MIN_HEIGHT = 'minHeight',
30
    MIN_WIDTH = 'minWidth',
31
    NODE = 'node',
32
    OFFSET_HEIGHT = 'offsetHeight',
33
    OFFSET_WIDTH = 'offsetWidth',
34
    PRESEVE_RATIO = 'preserveRatio',
35
    REGION = 'region',
36
    RESIZE_CONTRAINED = 'resizeConstrained',
37
    RIGHT = 'right',
38
    TICK_X = 'tickX',
39
    TICK_Y = 'tickY',
40
    TOP = 'top',
41
    WIDTH = 'width',
42
    VIEW = 'view',
43
    VIEWPORT_REGION = 'viewportRegion';
44
 
45
/**
46
A Resize plugin that will attempt to constrain the resize node to the boundaries.
47
@module resize
48
@submodule resize-contrain
49
@class ResizeConstrained
50
@param config {Object} Object literal specifying widget configuration properties.
51
@constructor
52
@extends Plugin.Base
53
@namespace Plugin
54
*/
55
 
56
function ResizeConstrained() {
57
    ResizeConstrained.superclass.constructor.apply(this, arguments);
58
}
59
 
60
Y.mix(ResizeConstrained, {
61
    NAME: RESIZE_CONTRAINED,
62
 
63
    NS: CON,
64
 
65
    ATTRS: {
66
        /**
67
        * Will attempt to constrain the resize node to the boundaries. Arguments:<br>
68
        * 'view': Contrain to Viewport<br>
69
        * '#selector_string': Constrain to this node<br>
70
        * '{Region Object}': An Object Literal containing a valid region (top, right, bottom, left) of page positions
71
        *
72
        * @attribute constrain
73
        * @type {String|Object|Node}
74
        */
75
        constrain: {
76
            setter: function(v) {
77
                if (v && (isNode(v) || isString(v) || v.nodeType)) {
78
                    v = Y.one(v);
79
                }
80
 
81
                return v;
82
            }
83
        },
84
 
85
        /**
86
         * The minimum height of the element
87
         *
88
         * @attribute minHeight
89
         * @default 15
90
         * @type Number
91
         */
92
        minHeight: {
93
            value: 15,
94
            validator: isNumber
95
        },
96
 
97
        /**
98
         * The minimum width of the element
99
         *
100
         * @attribute minWidth
101
         * @default 15
102
         * @type Number
103
         */
104
        minWidth: {
105
            value: 15,
106
            validator: isNumber
107
        },
108
 
109
        /**
110
         * The maximum height of the element
111
         *
112
         * @attribute maxHeight
113
         * @default Infinity
114
         * @type Number
115
         */
116
        maxHeight: {
117
            value: Infinity,
118
            validator: isNumber
119
        },
120
 
121
        /**
122
         * The maximum width of the element
123
         *
124
         * @attribute maxWidth
125
         * @default Infinity
126
         * @type Number
127
         */
128
        maxWidth: {
129
            value: Infinity,
130
            validator: isNumber
131
        },
132
 
133
        /**
134
         * Maintain the element's ratio when resizing.
135
         *
136
         * @attribute preserveRatio
137
         * @default false
138
         * @type boolean
139
         */
140
        preserveRatio: {
141
            value: false,
142
            validator: isBoolean
143
        },
144
 
145
        /**
146
         * The number of x ticks to span the resize to.
147
         *
148
         * @attribute tickX
149
         * @default false
150
         * @type Number | false
151
         */
152
        tickX: {
153
            value: false
154
        },
155
 
156
        /**
157
         * The number of y ticks to span the resize to.
158
         *
159
         * @attribute tickY
160
         * @default false
161
         * @type Number | false
162
         */
163
        tickY: {
164
            value: false
165
        }
166
    }
167
});
168
 
169
Y.extend(ResizeConstrained, Y.Plugin.Base, {
170
    /**
171
     * Stores the <code>constrain</code>
172
     * surrounding information retrieved from
173
     * <a href="Resize.html#method__getBoxSurroundingInfo">_getBoxSurroundingInfo</a>.
174
     *
175
     * @property constrainSurrounding
176
     * @type Object
177
     * @default null
178
     */
179
    constrainSurrounding: null,
180
 
181
    initializer: function() {
182
        var instance = this,
183
            host = instance.get(HOST);
184
 
185
        host.delegate.dd.plug(
186
            Y.Plugin.DDConstrained,
187
            {
188
                tickX: instance.get(TICK_X),
189
                tickY: instance.get(TICK_Y)
190
            }
191
        );
192
 
193
        host.after('resize:align', Y.bind(instance._handleResizeAlignEvent, instance));
194
        host.on('resize:start', Y.bind(instance._handleResizeStartEvent, instance));
195
    },
196
 
197
    /**
198
     * Helper method to update the current values on
199
     * <a href="Resize.html#property_info">info</a> to respect the
200
     * constrain node.
201
     *
202
     * @method _checkConstrain
203
     * @param {String} axis 'top' or 'left'
204
     * @param {String} axisConstrain 'bottom' or 'right'
205
     * @param {String} offset 'offsetHeight' or 'offsetWidth'
206
     * @protected
207
     */
208
    _checkConstrain: function(axis, axisConstrain, offset) {
209
        var instance = this,
210
            point1,
211
            point1Constrain,
212
            point2,
213
            point2Constrain,
214
            host = instance.get(HOST),
215
            info = host.info,
216
            constrainBorders = instance.constrainSurrounding.border,
217
            region = instance._getConstrainRegion();
218
 
219
        if (region) {
220
            point1 = info[axis] + info[offset];
221
            point1Constrain = region[axisConstrain] - toNumber(constrainBorders[capitalize(BORDER, axisConstrain, WIDTH)]);
222
 
223
            if (point1 >= point1Constrain) {
224
                info[offset] -= (point1 - point1Constrain);
225
            }
226
 
227
            point2 = info[axis];
228
            point2Constrain = region[axis] + toNumber(constrainBorders[capitalize(BORDER, axis, WIDTH)]);
229
 
230
            if (point2 <= point2Constrain) {
231
                info[axis] += (point2Constrain - point2);
232
                info[offset] -= (point2Constrain - point2);
233
            }
234
        }
235
    },
236
 
237
    /**
238
     * Update the current values on <a href="Resize.html#property_info">info</a>
239
     * to respect the maxHeight and minHeight.
240
     *
241
     * @method _checkHeight
242
     * @protected
243
     */
244
    _checkHeight: function() {
245
        var instance = this,
246
            host = instance.get(HOST),
247
            info = host.info,
248
            maxHeight = (instance.get(MAX_HEIGHT) + host.totalVSurrounding),
249
            minHeight = (instance.get(MIN_HEIGHT) + host.totalVSurrounding);
250
 
251
        instance._checkConstrain(TOP, BOTTOM, OFFSET_HEIGHT);
252
 
253
        if (info.offsetHeight > maxHeight) {
254
            host._checkSize(OFFSET_HEIGHT, maxHeight);
255
        }
256
 
257
        if (info.offsetHeight < minHeight) {
258
            host._checkSize(OFFSET_HEIGHT, minHeight);
259
        }
260
    },
261
 
262
    /**
263
     * Update the current values on <a href="Resize.html#property_info">info</a>
264
     * calculating the correct ratio for the other values.
265
     *
266
     * @method _checkRatio
267
     * @protected
268
     */
269
    _checkRatio: function() {
270
        var instance = this,
271
            host = instance.get(HOST),
272
            info = host.info,
273
            originalInfo = host.originalInfo,
274
            oWidth = originalInfo.offsetWidth,
275
            oHeight = originalInfo.offsetHeight,
276
            oTop = originalInfo.top,
277
            oLeft = originalInfo.left,
278
            oBottom = originalInfo.bottom,
279
            oRight = originalInfo.right,
280
            // wRatio/hRatio functions keep the ratio information always synced with the current info information
281
            // RETURN: percentage how much width/height has changed from the original width/height
282
            wRatio = function() {
283
                return (info.offsetWidth/oWidth);
284
            },
285
            hRatio = function() {
286
                return (info.offsetHeight/oHeight);
287
            },
288
            isClosestToHeight = host.changeHeightHandles,
289
            bottomDiff,
290
            constrainBorders,
291
            constrainRegion,
292
            leftDiff,
293
            rightDiff,
294
            topDiff;
295
 
296
        // check whether the resizable node is closest to height or not
297
        if (instance.get(CONSTRAIN) && host.changeHeightHandles && host.changeWidthHandles) {
298
            constrainRegion = instance._getConstrainRegion();
299
            constrainBorders = instance.constrainSurrounding.border;
300
            bottomDiff = (constrainRegion.bottom - toNumber(constrainBorders[BORDER_BOTTOM_WIDTH])) - oBottom;
301
            leftDiff = oLeft - (constrainRegion.left + toNumber(constrainBorders[BORDER_LEFT_WIDTH]));
302
            rightDiff = (constrainRegion.right - toNumber(constrainBorders[BORDER_RIGHT_WIDTH])) - oRight;
303
            topDiff = oTop - (constrainRegion.top + toNumber(constrainBorders[BORDER_TOP_WIDTH]));
304
 
305
            if (host.changeLeftHandles && host.changeTopHandles) {
306
                isClosestToHeight = (topDiff < leftDiff);
307
            }
308
            else if (host.changeLeftHandles) {
309
                isClosestToHeight = (bottomDiff < leftDiff);
310
            }
311
            else if (host.changeTopHandles) {
312
                isClosestToHeight = (topDiff < rightDiff);
313
            }
314
            else {
315
                isClosestToHeight = (bottomDiff < rightDiff);
316
            }
317
        }
318
 
319
        // when the height of the resizable element touch the border of the constrain first
320
        // force the offsetWidth to be calculated based on the height ratio
321
        if (isClosestToHeight) {
322
            info.offsetWidth = oWidth*hRatio();
323
            instance._checkWidth();
324
            info.offsetHeight = oHeight*wRatio();
325
        }
326
        else {
327
            info.offsetHeight = oHeight*wRatio();
328
            instance._checkHeight();
329
            info.offsetWidth = oWidth*hRatio();
330
        }
331
 
332
        // fixing the top on handles which are able to change top
333
        // the idea here is change the top based on how much the height has changed instead of follow the dy
334
        if (host.changeTopHandles) {
335
            info.top = oTop + (oHeight - info.offsetHeight);
336
        }
337
 
338
        // fixing the left on handles which are able to change left
339
        // the idea here is change the left based on how much the width has changed instead of follow the dx
340
        if (host.changeLeftHandles) {
341
            info.left = oLeft + (oWidth - info.offsetWidth);
342
        }
343
 
344
        // rounding values to avoid pixel jumpings
345
        Y.each(info, function(value, key) {
346
            if (isNumber(value)) {
347
                info[key] = Math.round(value);
348
            }
349
        });
350
    },
351
 
352
    /**
353
     * Check whether the resizable node is inside the constrain region.
354
     *
355
     * @method _checkRegion
356
     * @protected
357
     * @return {boolean}
358
     */
359
    _checkRegion: function() {
360
        var instance = this,
361
            host = instance.get(HOST),
362
            region = instance._getConstrainRegion();
363
 
364
        return Y.DOM.inRegion(null, region, true, host.info);
365
    },
366
 
367
    /**
368
     * Update the current values on <a href="Resize.html#property_info">info</a>
369
     * to respect the maxWidth and minWidth.
370
     *
371
     * @method _checkWidth
372
     * @protected
373
     */
374
    _checkWidth: function() {
375
        var instance = this,
376
            host = instance.get(HOST),
377
            info = host.info,
378
            maxWidth = (instance.get(MAX_WIDTH) + host.totalHSurrounding),
379
            minWidth = (instance.get(MIN_WIDTH) + host.totalHSurrounding);
380
 
381
        instance._checkConstrain(LEFT, RIGHT, OFFSET_WIDTH);
382
 
383
        if (info.offsetWidth < minWidth) {
384
            host._checkSize(OFFSET_WIDTH, minWidth);
385
        }
386
 
387
        if (info.offsetWidth > maxWidth) {
388
            host._checkSize(OFFSET_WIDTH, maxWidth);
389
        }
390
    },
391
 
392
    /**
393
     * Get the constrain region based on the <code>constrain</code>
394
     * attribute.
395
     *
396
     * @method _getConstrainRegion
397
     * @protected
398
     * @return {Object Region}
399
     */
400
    _getConstrainRegion: function() {
401
        var instance = this,
402
            host = instance.get(HOST),
403
            node = host.get(NODE),
404
            constrain = instance.get(CONSTRAIN),
405
            region = null;
406
 
407
        if (constrain) {
408
            if (constrain === VIEW) {
409
                region = node.get(VIEWPORT_REGION);
410
            }
411
            else if (isNode(constrain)) {
412
                region = constrain.get(REGION);
413
            }
414
            else {
415
                region = constrain;
416
            }
417
        }
418
 
419
        return region;
420
    },
421
 
422
    _handleResizeAlignEvent: function() {
423
        var instance = this,
424
            host = instance.get(HOST);
425
 
426
        // check the max/min height and locking top when these values are reach
427
        instance._checkHeight();
428
 
429
        // check the max/min width and locking left when these values are reach
430
        instance._checkWidth();
431
 
432
        // calculating the ratio, for proportionally resizing
433
        if (instance.get(PRESEVE_RATIO)) {
434
            instance._checkRatio();
435
        }
436
 
437
        if (instance.get(CONSTRAIN) && !instance._checkRegion()) {
438
            host.info = host.lastInfo;
439
        }
440
    },
441
 
442
    _handleResizeStartEvent: function() {
443
        var instance = this,
444
            constrain = instance.get(CONSTRAIN),
445
            host = instance.get(HOST);
446
 
447
        instance.constrainSurrounding = host._getBoxSurroundingInfo(constrain);
448
    }
449
});
450
 
451
Y.namespace('Plugin');
452
Y.Plugin.ResizeConstrained = ResizeConstrained;
453
 
454
 
455
}, '3.18.1', {"requires": ["plugin", "resize-base"]});