source: Dev/branches/jQueryUI/client/js/jquery/ui/jquery.ui.resizable.js @ 249

Last change on this file since 249 was 249, checked in by hendrikvanantwerpen, 13 years ago

This one's for Subversion, because it's so close...

First widget (stripped down sequencer).
Seperated client and server code in two direcotry trees.

File size: 27.1 KB
Line 
1/*
2 * jQuery UI Resizable 1.8.17
3 *
4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
7 *
8 * http://docs.jquery.com/UI/Resizables
9 *
10 * Depends:
11 *      jquery.ui.core.js
12 *      jquery.ui.mouse.js
13 *      jquery.ui.widget.js
14 */
15(function( $, undefined ) {
16
17$.widget("ui.resizable", $.ui.mouse, {
18        widgetEventPrefix: "resize",
19        options: {
20                alsoResize: false,
21                animate: false,
22                animateDuration: "slow",
23                animateEasing: "swing",
24                aspectRatio: false,
25                autoHide: false,
26                containment: false,
27                ghost: false,
28                grid: false,
29                handles: "e,s,se",
30                helper: false,
31                maxHeight: null,
32                maxWidth: null,
33                minHeight: 10,
34                minWidth: 10,
35                zIndex: 1000
36        },
37        _create: function() {
38
39                var self = this, o = this.options;
40                this.element.addClass("ui-resizable");
41
42                $.extend(this, {
43                        _aspectRatio: !!(o.aspectRatio),
44                        aspectRatio: o.aspectRatio,
45                        originalElement: this.element,
46                        _proportionallyResizeElements: [],
47                        _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
48                });
49
50                //Wrap the element if it cannot hold child nodes
51                if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
52
53                        //Opera fix for relative positioning
54                        if (/relative/.test(this.element.css('position')) && $.browser.opera)
55                                this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
56
57                        //Create a wrapper element and set the wrapper to the new current internal element
58                        this.element.wrap(
59                                $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
60                                        position: this.element.css('position'),
61                                        width: this.element.outerWidth(),
62                                        height: this.element.outerHeight(),
63                                        top: this.element.css('top'),
64                                        left: this.element.css('left')
65                                })
66                        );
67
68                        //Overwrite the original this.element
69                        this.element = this.element.parent().data(
70                                "resizable", this.element.data('resizable')
71                        );
72
73                        this.elementIsWrapper = true;
74
75                        //Move margins to the wrapper
76                        this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
77                        this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
78
79                        //Prevent Safari textarea resize
80                        this.originalResizeStyle = this.originalElement.css('resize');
81                        this.originalElement.css('resize', 'none');
82
83                        //Push the actual element to our proportionallyResize internal array
84                        this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
85
86                        // avoid IE jump (hard set the margin)
87                        this.originalElement.css({ margin: this.originalElement.css('margin') });
88
89                        // fix handlers offset
90                        this._proportionallyResize();
91
92                }
93
94                this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
95                if(this.handles.constructor == String) {
96
97                        if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
98                        var n = this.handles.split(","); this.handles = {};
99
100                        for(var i = 0; i < n.length; i++) {
101
102                                var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
103                                var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
104
105                                // increase zIndex of sw, se, ne, nw axis
106                                //TODO : this modifies original option
107                                if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
108
109                                //TODO : What's going on here?
110                                if ('se' == handle) {
111                                        axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
112                                };
113
114                                //Insert into internal handles object and append to element
115                                this.handles[handle] = '.ui-resizable-'+handle;
116                                this.element.append(axis);
117                        }
118
119                }
120
121                this._renderAxis = function(target) {
122
123                        target = target || this.element;
124
125                        for(var i in this.handles) {
126
127                                if(this.handles[i].constructor == String)
128                                        this.handles[i] = $(this.handles[i], this.element).show();
129
130                                //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
131                                if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
132
133                                        var axis = $(this.handles[i], this.element), padWrapper = 0;
134
135                                        //Checking the correct pad and border
136                                        padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
137
138                                        //The padding type i have to apply...
139                                        var padPos = [ 'padding',
140                                                /ne|nw|n/.test(i) ? 'Top' :
141                                                /se|sw|s/.test(i) ? 'Bottom' :
142                                                /^e$/.test(i) ? 'Right' : 'Left' ].join("");
143
144                                        target.css(padPos, padWrapper);
145
146                                        this._proportionallyResize();
147
148                                }
149
150                                //TODO: What's that good for? There's not anything to be executed left
151                                if(!$(this.handles[i]).length)
152                                        continue;
153
154                        }
155                };
156
157                //TODO: make renderAxis a prototype function
158                this._renderAxis(this.element);
159
160                this._handles = $('.ui-resizable-handle', this.element)
161                        .disableSelection();
162
163                //Matching axis name
164                this._handles.mouseover(function() {
165                        if (!self.resizing) {
166                                if (this.className)
167                                        var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
168                                //Axis, default = se
169                                self.axis = axis && axis[1] ? axis[1] : 'se';
170                        }
171                });
172
173                //If we want to auto hide the elements
174                if (o.autoHide) {
175                        this._handles.hide();
176                        $(this.element)
177                                .addClass("ui-resizable-autohide")
178                                .hover(function() {
179                                        if (o.disabled) return;
180                                        $(this).removeClass("ui-resizable-autohide");
181                                        self._handles.show();
182                                },
183                                function(){
184                                        if (o.disabled) return;
185                                        if (!self.resizing) {
186                                                $(this).addClass("ui-resizable-autohide");
187                                                self._handles.hide();
188                                        }
189                                });
190                }
191
192                //Initialize the mouse interaction
193                this._mouseInit();
194
195        },
196
197        destroy: function() {
198
199                this._mouseDestroy();
200
201                var _destroy = function(exp) {
202                        $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
203                                .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
204                };
205
206                //TODO: Unwrap at same DOM position
207                if (this.elementIsWrapper) {
208                        _destroy(this.element);
209                        var wrapper = this.element;
210                        wrapper.after(
211                                this.originalElement.css({
212                                        position: wrapper.css('position'),
213                                        width: wrapper.outerWidth(),
214                                        height: wrapper.outerHeight(),
215                                        top: wrapper.css('top'),
216                                        left: wrapper.css('left')
217                                })
218                        ).remove();
219                }
220
221                this.originalElement.css('resize', this.originalResizeStyle);
222                _destroy(this.originalElement);
223
224                return this;
225        },
226
227        _mouseCapture: function(event) {
228                var handle = false;
229                for (var i in this.handles) {
230                        if ($(this.handles[i])[0] == event.target) {
231                                handle = true;
232                        }
233                }
234
235                return !this.options.disabled && handle;
236        },
237
238        _mouseStart: function(event) {
239
240                var o = this.options, iniPos = this.element.position(), el = this.element;
241
242                this.resizing = true;
243                this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
244
245                // bugfix for http://dev.jquery.com/ticket/1749
246                if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
247                        el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
248                }
249
250                //Opera fixing relative position
251                if ($.browser.opera && (/relative/).test(el.css('position')))
252                        el.css({ position: 'relative', top: 'auto', left: 'auto' });
253
254                this._renderProxy();
255
256                var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
257
258                if (o.containment) {
259                        curleft += $(o.containment).scrollLeft() || 0;
260                        curtop += $(o.containment).scrollTop() || 0;
261                }
262
263                //Store needed variables
264                this.offset = this.helper.offset();
265                this.position = { left: curleft, top: curtop };
266                this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
267                this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
268                this.originalPosition = { left: curleft, top: curtop };
269                this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
270                this.originalMousePosition = { left: event.pageX, top: event.pageY };
271
272                //Aspect Ratio
273                this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
274
275            var cursor = $('.ui-resizable-' + this.axis).css('cursor');
276            $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
277
278                el.addClass("ui-resizable-resizing");
279                this._propagate("start", event);
280                return true;
281        },
282
283        _mouseDrag: function(event) {
284
285                //Increase performance, avoid regex
286                var el = this.helper, o = this.options, props = {},
287                        self = this, smp = this.originalMousePosition, a = this.axis;
288
289                var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
290                var trigger = this._change[a];
291                if (!trigger) return false;
292
293                // Calculate the attrs that will be change
294                var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
295
296                // Put this in the mouseDrag handler since the user can start pressing shift while resizing
297                this._updateVirtualBoundaries(event.shiftKey);
298                if (this._aspectRatio || event.shiftKey)
299                        data = this._updateRatio(data, event);
300
301                data = this._respectSize(data, event);
302
303                // plugins callbacks need to be called first
304                this._propagate("resize", event);
305
306                el.css({
307                        top: this.position.top + "px", left: this.position.left + "px",
308                        width: this.size.width + "px", height: this.size.height + "px"
309                });
310
311                if (!this._helper && this._proportionallyResizeElements.length)
312                        this._proportionallyResize();
313
314                this._updateCache(data);
315
316                // calling the user callback at the end
317                this._trigger('resize', event, this.ui());
318
319                return false;
320        },
321
322        _mouseStop: function(event) {
323
324                this.resizing = false;
325                var o = this.options, self = this;
326
327                if(this._helper) {
328                        var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
329                                soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
330                                soffsetw = ista ? 0 : self.sizeDiff.width;
331
332                        var s = { width: (self.helper.width()  - soffsetw), height: (self.helper.height() - soffseth) },
333                                left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
334                                top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
335
336                        if (!o.animate)
337                                this.element.css($.extend(s, { top: top, left: left }));
338
339                        self.helper.height(self.size.height);
340                        self.helper.width(self.size.width);
341
342                        if (this._helper && !o.animate) this._proportionallyResize();
343                }
344
345                $('body').css('cursor', 'auto');
346
347                this.element.removeClass("ui-resizable-resizing");
348
349                this._propagate("stop", event);
350
351                if (this._helper) this.helper.remove();
352                return false;
353
354        },
355
356    _updateVirtualBoundaries: function(forceAspectRatio) {
357        var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
358
359        b = {
360            minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
361            maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
362            minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
363            maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
364        };
365
366        if(this._aspectRatio || forceAspectRatio) {
367            // We want to create an enclosing box whose aspect ration is the requested one
368            // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
369            pMinWidth = b.minHeight * this.aspectRatio;
370            pMinHeight = b.minWidth / this.aspectRatio;
371            pMaxWidth = b.maxHeight * this.aspectRatio;
372            pMaxHeight = b.maxWidth / this.aspectRatio;
373
374            if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
375            if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
376            if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
377            if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
378        }
379        this._vBoundaries = b;
380    },
381
382        _updateCache: function(data) {
383                var o = this.options;
384                this.offset = this.helper.offset();
385                if (isNumber(data.left)) this.position.left = data.left;
386                if (isNumber(data.top)) this.position.top = data.top;
387                if (isNumber(data.height)) this.size.height = data.height;
388                if (isNumber(data.width)) this.size.width = data.width;
389        },
390
391        _updateRatio: function(data, event) {
392
393                var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
394
395                if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
396                else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
397
398                if (a == 'sw') {
399                        data.left = cpos.left + (csize.width - data.width);
400                        data.top = null;
401                }
402                if (a == 'nw') {
403                        data.top = cpos.top + (csize.height - data.height);
404                        data.left = cpos.left + (csize.width - data.width);
405                }
406
407                return data;
408        },
409
410        _respectSize: function(data, event) {
411
412                var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
413                                ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
414                                        isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
415
416                if (isminw) data.width = o.minWidth;
417                if (isminh) data.height = o.minHeight;
418                if (ismaxw) data.width = o.maxWidth;
419                if (ismaxh) data.height = o.maxHeight;
420
421                var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
422                var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
423
424                if (isminw && cw) data.left = dw - o.minWidth;
425                if (ismaxw && cw) data.left = dw - o.maxWidth;
426                if (isminh && ch)       data.top = dh - o.minHeight;
427                if (ismaxh && ch)       data.top = dh - o.maxHeight;
428
429                // fixing jump error on top/left - bug #2330
430                var isNotwh = !data.width && !data.height;
431                if (isNotwh && !data.left && data.top) data.top = null;
432                else if (isNotwh && !data.top && data.left) data.left = null;
433
434                return data;
435        },
436
437        _proportionallyResize: function() {
438
439                var o = this.options;
440                if (!this._proportionallyResizeElements.length) return;
441                var element = this.helper || this.element;
442
443                for (var i=0; i < this._proportionallyResizeElements.length; i++) {
444
445                        var prel = this._proportionallyResizeElements[i];
446
447                        if (!this.borderDif) {
448                                var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
449                                        p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
450
451                                this.borderDif = $.map(b, function(v, i) {
452                                        var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
453                                        return border + padding;
454                                });
455                        }
456
457                        if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
458                                continue;
459
460                        prel.css({
461                                height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
462                                width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
463                        });
464
465                };
466
467        },
468
469        _renderProxy: function() {
470
471                var el = this.element, o = this.options;
472                this.elementOffset = el.offset();
473
474                if(this._helper) {
475
476                        this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
477
478                        // fix ie6 offset TODO: This seems broken
479                        var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
480                        pxyoffset = ( ie6 ? 2 : -1 );
481
482                        this.helper.addClass(this._helper).css({
483                                width: this.element.outerWidth() + pxyoffset,
484                                height: this.element.outerHeight() + pxyoffset,
485                                position: 'absolute',
486                                left: this.elementOffset.left - ie6offset +'px',
487                                top: this.elementOffset.top - ie6offset +'px',
488                                zIndex: ++o.zIndex //TODO: Don't modify option
489                        });
490
491                        this.helper
492                                .appendTo("body")
493                                .disableSelection();
494
495                } else {
496                        this.helper = this.element;
497                }
498
499        },
500
501        _change: {
502                e: function(event, dx, dy) {
503                        return { width: this.originalSize.width + dx };
504                },
505                w: function(event, dx, dy) {
506                        var o = this.options, cs = this.originalSize, sp = this.originalPosition;
507                        return { left: sp.left + dx, width: cs.width - dx };
508                },
509                n: function(event, dx, dy) {
510                        var o = this.options, cs = this.originalSize, sp = this.originalPosition;
511                        return { top: sp.top + dy, height: cs.height - dy };
512                },
513                s: function(event, dx, dy) {
514                        return { height: this.originalSize.height + dy };
515                },
516                se: function(event, dx, dy) {
517                        return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
518                },
519                sw: function(event, dx, dy) {
520                        return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
521                },
522                ne: function(event, dx, dy) {
523                        return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
524                },
525                nw: function(event, dx, dy) {
526                        return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
527                }
528        },
529
530        _propagate: function(n, event) {
531                $.ui.plugin.call(this, n, [event, this.ui()]);
532                (n != "resize" && this._trigger(n, event, this.ui()));
533        },
534
535        plugins: {},
536
537        ui: function() {
538                return {
539                        originalElement: this.originalElement,
540                        element: this.element,
541                        helper: this.helper,
542                        position: this.position,
543                        size: this.size,
544                        originalSize: this.originalSize,
545                        originalPosition: this.originalPosition
546                };
547        }
548
549});
550
551$.extend($.ui.resizable, {
552        version: "1.8.17"
553});
554
555/*
556 * Resizable Extensions
557 */
558
559$.ui.plugin.add("resizable", "alsoResize", {
560
561        start: function (event, ui) {
562                var self = $(this).data("resizable"), o = self.options;
563
564                var _store = function (exp) {
565                        $(exp).each(function() {
566                                var el = $(this);
567                                el.data("resizable-alsoresize", {
568                                        width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
569                                        left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
570                                        position: el.css('position') // to reset Opera on stop()
571                                });
572                        });
573                };
574
575                if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
576                        if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
577                        else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
578                }else{
579                        _store(o.alsoResize);
580                }
581        },
582
583        resize: function (event, ui) {
584                var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
585
586                var delta = {
587                        height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
588                        top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
589                },
590
591                _alsoResize = function (exp, c) {
592                        $(exp).each(function() {
593                                var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
594                                        css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
595
596                                $.each(css, function (i, prop) {
597                                        var sum = (start[prop]||0) + (delta[prop]||0);
598                                        if (sum && sum >= 0)
599                                                style[prop] = sum || null;
600                                });
601
602                                // Opera fixing relative position
603                                if ($.browser.opera && /relative/.test(el.css('position'))) {
604                                        self._revertToRelativePosition = true;
605                                        el.css({ position: 'absolute', top: 'auto', left: 'auto' });
606                                }
607
608                                el.css(style);
609                        });
610                };
611
612                if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
613                        $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
614                }else{
615                        _alsoResize(o.alsoResize);
616                }
617        },
618
619        stop: function (event, ui) {
620                var self = $(this).data("resizable"), o = self.options;
621
622                var _reset = function (exp) {
623                        $(exp).each(function() {
624                                var el = $(this);
625                                // reset position for Opera - no need to verify it was changed
626                                el.css({ position: el.data("resizable-alsoresize").position });
627                        });
628                };
629
630                if (self._revertToRelativePosition) {
631                        self._revertToRelativePosition = false;
632                        if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
633                                $.each(o.alsoResize, function (exp) { _reset(exp); });
634                        }else{
635                                _reset(o.alsoResize);
636                        }
637                }
638
639                $(this).removeData("resizable-alsoresize");
640        }
641});
642
643$.ui.plugin.add("resizable", "animate", {
644
645        stop: function(event, ui) {
646                var self = $(this).data("resizable"), o = self.options;
647
648                var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
649                                        soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
650                                                soffsetw = ista ? 0 : self.sizeDiff.width;
651
652                var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
653                                        left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
654                                                top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
655
656                self.element.animate(
657                        $.extend(style, top && left ? { top: top, left: left } : {}), {
658                                duration: o.animateDuration,
659                                easing: o.animateEasing,
660                                step: function() {
661
662                                        var data = {
663                                                width: parseInt(self.element.css('width'), 10),
664                                                height: parseInt(self.element.css('height'), 10),
665                                                top: parseInt(self.element.css('top'), 10),
666                                                left: parseInt(self.element.css('left'), 10)
667                                        };
668
669                                        if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
670
671                                        // propagating resize, and updating values for each animation step
672                                        self._updateCache(data);
673                                        self._propagate("resize", event);
674
675                                }
676                        }
677                );
678        }
679
680});
681
682$.ui.plugin.add("resizable", "containment", {
683
684        start: function(event, ui) {
685                var self = $(this).data("resizable"), o = self.options, el = self.element;
686                var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
687                if (!ce) return;
688
689                self.containerElement = $(ce);
690
691                if (/document/.test(oc) || oc == document) {
692                        self.containerOffset = { left: 0, top: 0 };
693                        self.containerPosition = { left: 0, top: 0 };
694
695                        self.parentData = {
696                                element: $(document), left: 0, top: 0,
697                                width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
698                        };
699                }
700
701                // i'm a node, so compute top, left, right, bottom
702                else {
703                        var element = $(ce), p = [];
704                        $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
705
706                        self.containerOffset = element.offset();
707                        self.containerPosition = element.position();
708                        self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
709
710                        var co = self.containerOffset, ch = self.containerSize.height,  cw = self.containerSize.width,
711                                                width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
712
713                        self.parentData = {
714                                element: ce, left: co.left, top: co.top, width: width, height: height
715                        };
716                }
717        },
718
719        resize: function(event, ui) {
720                var self = $(this).data("resizable"), o = self.options,
721                                ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
722                                pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
723
724                if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
725
726                if (cp.left < (self._helper ? co.left : 0)) {
727                        self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
728                        if (pRatio) self.size.height = self.size.width / o.aspectRatio;
729                        self.position.left = o.helper ? co.left : 0;
730                }
731
732                if (cp.top < (self._helper ? co.top : 0)) {
733                        self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
734                        if (pRatio) self.size.width = self.size.height * o.aspectRatio;
735                        self.position.top = self._helper ? co.top : 0;
736                }
737
738                self.offset.left = self.parentData.left+self.position.left;
739                self.offset.top = self.parentData.top+self.position.top;
740
741                var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
742                                        hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
743
744                var isParent = self.containerElement.get(0) == self.element.parent().get(0),
745                    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
746
747                if(isParent && isOffsetRelative) woset -= self.parentData.left;
748
749                if (woset + self.size.width >= self.parentData.width) {
750                        self.size.width = self.parentData.width - woset;
751                        if (pRatio) self.size.height = self.size.width / self.aspectRatio;
752                }
753
754                if (hoset + self.size.height >= self.parentData.height) {
755                        self.size.height = self.parentData.height - hoset;
756                        if (pRatio) self.size.width = self.size.height * self.aspectRatio;
757                }
758        },
759
760        stop: function(event, ui){
761                var self = $(this).data("resizable"), o = self.options, cp = self.position,
762                                co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
763
764                var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
765
766                if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
767                        $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
768
769                if (self._helper && !o.animate && (/static/).test(ce.css('position')))
770                        $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
771
772        }
773});
774
775$.ui.plugin.add("resizable", "ghost", {
776
777        start: function(event, ui) {
778
779                var self = $(this).data("resizable"), o = self.options, cs = self.size;
780
781                self.ghost = self.originalElement.clone();
782                self.ghost
783                        .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
784                        .addClass('ui-resizable-ghost')
785                        .addClass(typeof o.ghost == 'string' ? o.ghost : '');
786
787                self.ghost.appendTo(self.helper);
788
789        },
790
791        resize: function(event, ui){
792                var self = $(this).data("resizable"), o = self.options;
793                if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
794        },
795
796        stop: function(event, ui){
797                var self = $(this).data("resizable"), o = self.options;
798                if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
799        }
800
801});
802
803$.ui.plugin.add("resizable", "grid", {
804
805        resize: function(event, ui) {
806                var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
807                o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
808                var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
809
810                if (/^(se|s|e)$/.test(a)) {
811                        self.size.width = os.width + ox;
812                        self.size.height = os.height + oy;
813                }
814                else if (/^(ne)$/.test(a)) {
815                        self.size.width = os.width + ox;
816                        self.size.height = os.height + oy;
817                        self.position.top = op.top - oy;
818                }
819                else if (/^(sw)$/.test(a)) {
820                        self.size.width = os.width + ox;
821                        self.size.height = os.height + oy;
822                        self.position.left = op.left - ox;
823                }
824                else {
825                        self.size.width = os.width + ox;
826                        self.size.height = os.height + oy;
827                        self.position.top = op.top - oy;
828                        self.position.left = op.left - ox;
829                }
830        }
831
832});
833
834var num = function(v) {
835        return parseInt(v, 10) || 0;
836};
837
838var isNumber = function(value) {
839        return !isNaN(parseInt(value, 10));
840};
841
842})(jQuery);
Note: See TracBrowser for help on using the repository browser.