source: trunk/themes/default/js/ui/jquery.ui.resizable.js @ 9559

Last change on this file since 9559 was 9559, checked in by patdenice, 13 years ago

Update jQuery UI to 1.8.10.
Improve jquery ui management in template class.

File size: 25.7 KB
Line 
1/*
2 * jQuery UI Resizable 1.8.10
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                                        $(this).removeClass("ui-resizable-autohide");
180                                        self._handles.show();
181                                },
182                                function(){
183                                        if (!self.resizing) {
184                                                $(this).addClass("ui-resizable-autohide");
185                                                self._handles.hide();
186                                        }
187                                });
188                }
189
190                //Initialize the mouse interaction
191                this._mouseInit();
192
193        },
194
195        destroy: function() {
196
197                this._mouseDestroy();
198
199                var _destroy = function(exp) {
200                        $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
201                                .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
202                };
203
204                //TODO: Unwrap at same DOM position
205                if (this.elementIsWrapper) {
206                        _destroy(this.element);
207                        var wrapper = this.element;
208                        wrapper.after(
209                                this.originalElement.css({
210                                        position: wrapper.css('position'),
211                                        width: wrapper.outerWidth(),
212                                        height: wrapper.outerHeight(),
213                                        top: wrapper.css('top'),
214                                        left: wrapper.css('left')
215                                })
216                        ).remove();
217                }
218
219                this.originalElement.css('resize', this.originalResizeStyle);
220                _destroy(this.originalElement);
221
222                return this;
223        },
224
225        _mouseCapture: function(event) {
226                var handle = false;
227                for (var i in this.handles) {
228                        if ($(this.handles[i])[0] == event.target) {
229                                handle = true;
230                        }
231                }
232
233                return !this.options.disabled && handle;
234        },
235
236        _mouseStart: function(event) {
237
238                var o = this.options, iniPos = this.element.position(), el = this.element;
239
240                this.resizing = true;
241                this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
242
243                // bugfix for http://dev.jquery.com/ticket/1749
244                if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
245                        el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
246                }
247
248                //Opera fixing relative position
249                if ($.browser.opera && (/relative/).test(el.css('position')))
250                        el.css({ position: 'relative', top: 'auto', left: 'auto' });
251
252                this._renderProxy();
253
254                var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
255
256                if (o.containment) {
257                        curleft += $(o.containment).scrollLeft() || 0;
258                        curtop += $(o.containment).scrollTop() || 0;
259                }
260
261                //Store needed variables
262                this.offset = this.helper.offset();
263                this.position = { left: curleft, top: curtop };
264                this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
265                this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
266                this.originalPosition = { left: curleft, top: curtop };
267                this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
268                this.originalMousePosition = { left: event.pageX, top: event.pageY };
269
270                //Aspect Ratio
271                this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
272
273            var cursor = $('.ui-resizable-' + this.axis).css('cursor');
274            $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
275
276                el.addClass("ui-resizable-resizing");
277                this._propagate("start", event);
278                return true;
279        },
280
281        _mouseDrag: function(event) {
282
283                //Increase performance, avoid regex
284                var el = this.helper, o = this.options, props = {},
285                        self = this, smp = this.originalMousePosition, a = this.axis;
286
287                var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
288                var trigger = this._change[a];
289                if (!trigger) return false;
290
291                // Calculate the attrs that will be change
292                var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
293
294                if (this._aspectRatio || event.shiftKey)
295                        data = this._updateRatio(data, event);
296
297                data = this._respectSize(data, event);
298
299                // plugins callbacks need to be called first
300                this._propagate("resize", event);
301
302                el.css({
303                        top: this.position.top + "px", left: this.position.left + "px",
304                        width: this.size.width + "px", height: this.size.height + "px"
305                });
306
307                if (!this._helper && this._proportionallyResizeElements.length)
308                        this._proportionallyResize();
309
310                this._updateCache(data);
311
312                // calling the user callback at the end
313                this._trigger('resize', event, this.ui());
314
315                return false;
316        },
317
318        _mouseStop: function(event) {
319
320                this.resizing = false;
321                var o = this.options, self = this;
322
323                if(this._helper) {
324                        var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
325                                soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
326                                soffsetw = ista ? 0 : self.sizeDiff.width;
327
328                        var s = { width: (self.helper.width()  - soffsetw), height: (self.helper.height() - soffseth) },
329                                left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
330                                top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
331
332                        if (!o.animate)
333                                this.element.css($.extend(s, { top: top, left: left }));
334
335                        self.helper.height(self.size.height);
336                        self.helper.width(self.size.width);
337
338                        if (this._helper && !o.animate) this._proportionallyResize();
339                }
340
341                $('body').css('cursor', 'auto');
342
343                this.element.removeClass("ui-resizable-resizing");
344
345                this._propagate("stop", event);
346
347                if (this._helper) this.helper.remove();
348                return false;
349
350        },
351
352        _updateCache: function(data) {
353                var o = this.options;
354                this.offset = this.helper.offset();
355                if (isNumber(data.left)) this.position.left = data.left;
356                if (isNumber(data.top)) this.position.top = data.top;
357                if (isNumber(data.height)) this.size.height = data.height;
358                if (isNumber(data.width)) this.size.width = data.width;
359        },
360
361        _updateRatio: function(data, event) {
362
363                var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
364
365                if (data.height) data.width = (csize.height * this.aspectRatio);
366                else if (data.width) data.height = (csize.width / this.aspectRatio);
367
368                if (a == 'sw') {
369                        data.left = cpos.left + (csize.width - data.width);
370                        data.top = null;
371                }
372                if (a == 'nw') {
373                        data.top = cpos.top + (csize.height - data.height);
374                        data.left = cpos.left + (csize.width - data.width);
375                }
376
377                return data;
378        },
379
380        _respectSize: function(data, event) {
381
382                var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
383                                ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
384                                        isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
385
386                if (isminw) data.width = o.minWidth;
387                if (isminh) data.height = o.minHeight;
388                if (ismaxw) data.width = o.maxWidth;
389                if (ismaxh) data.height = o.maxHeight;
390
391                var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
392                var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
393
394                if (isminw && cw) data.left = dw - o.minWidth;
395                if (ismaxw && cw) data.left = dw - o.maxWidth;
396                if (isminh && ch)       data.top = dh - o.minHeight;
397                if (ismaxh && ch)       data.top = dh - o.maxHeight;
398
399                // fixing jump error on top/left - bug #2330
400                var isNotwh = !data.width && !data.height;
401                if (isNotwh && !data.left && data.top) data.top = null;
402                else if (isNotwh && !data.top && data.left) data.left = null;
403
404                return data;
405        },
406
407        _proportionallyResize: function() {
408
409                var o = this.options;
410                if (!this._proportionallyResizeElements.length) return;
411                var element = this.helper || this.element;
412
413                for (var i=0; i < this._proportionallyResizeElements.length; i++) {
414
415                        var prel = this._proportionallyResizeElements[i];
416
417                        if (!this.borderDif) {
418                                var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
419                                        p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
420
421                                this.borderDif = $.map(b, function(v, i) {
422                                        var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
423                                        return border + padding;
424                                });
425                        }
426
427                        if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
428                                continue;
429
430                        prel.css({
431                                height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
432                                width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
433                        });
434
435                };
436
437        },
438
439        _renderProxy: function() {
440
441                var el = this.element, o = this.options;
442                this.elementOffset = el.offset();
443
444                if(this._helper) {
445
446                        this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
447
448                        // fix ie6 offset TODO: This seems broken
449                        var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
450                        pxyoffset = ( ie6 ? 2 : -1 );
451
452                        this.helper.addClass(this._helper).css({
453                                width: this.element.outerWidth() + pxyoffset,
454                                height: this.element.outerHeight() + pxyoffset,
455                                position: 'absolute',
456                                left: this.elementOffset.left - ie6offset +'px',
457                                top: this.elementOffset.top - ie6offset +'px',
458                                zIndex: ++o.zIndex //TODO: Don't modify option
459                        });
460
461                        this.helper
462                                .appendTo("body")
463                                .disableSelection();
464
465                } else {
466                        this.helper = this.element;
467                }
468
469        },
470
471        _change: {
472                e: function(event, dx, dy) {
473                        return { width: this.originalSize.width + dx };
474                },
475                w: function(event, dx, dy) {
476                        var o = this.options, cs = this.originalSize, sp = this.originalPosition;
477                        return { left: sp.left + dx, width: cs.width - dx };
478                },
479                n: function(event, dx, dy) {
480                        var o = this.options, cs = this.originalSize, sp = this.originalPosition;
481                        return { top: sp.top + dy, height: cs.height - dy };
482                },
483                s: function(event, dx, dy) {
484                        return { height: this.originalSize.height + dy };
485                },
486                se: function(event, dx, dy) {
487                        return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
488                },
489                sw: function(event, dx, dy) {
490                        return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
491                },
492                ne: function(event, dx, dy) {
493                        return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
494                },
495                nw: function(event, dx, dy) {
496                        return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
497                }
498        },
499
500        _propagate: function(n, event) {
501                $.ui.plugin.call(this, n, [event, this.ui()]);
502                (n != "resize" && this._trigger(n, event, this.ui()));
503        },
504
505        plugins: {},
506
507        ui: function() {
508                return {
509                        originalElement: this.originalElement,
510                        element: this.element,
511                        helper: this.helper,
512                        position: this.position,
513                        size: this.size,
514                        originalSize: this.originalSize,
515                        originalPosition: this.originalPosition
516                };
517        }
518
519});
520
521$.extend($.ui.resizable, {
522        version: "1.8.10"
523});
524
525/*
526 * Resizable Extensions
527 */
528
529$.ui.plugin.add("resizable", "alsoResize", {
530
531        start: function (event, ui) {
532                var self = $(this).data("resizable"), o = self.options;
533
534                var _store = function (exp) {
535                        $(exp).each(function() {
536                                var el = $(this);
537                                el.data("resizable-alsoresize", {
538                                        width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
539                                        left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
540                                        position: el.css('position') // to reset Opera on stop()
541                                });
542                        });
543                };
544
545                if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
546                        if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
547                        else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
548                }else{
549                        _store(o.alsoResize);
550                }
551        },
552
553        resize: function (event, ui) {
554                var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
555
556                var delta = {
557                        height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
558                        top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
559                },
560
561                _alsoResize = function (exp, c) {
562                        $(exp).each(function() {
563                                var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
564                                        css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
565
566                                $.each(css, function (i, prop) {
567                                        var sum = (start[prop]||0) + (delta[prop]||0);
568                                        if (sum && sum >= 0)
569                                                style[prop] = sum || null;
570                                });
571
572                                // Opera fixing relative position
573                                if ($.browser.opera && /relative/.test(el.css('position'))) {
574                                        self._revertToRelativePosition = true;
575                                        el.css({ position: 'absolute', top: 'auto', left: 'auto' });
576                                }
577
578                                el.css(style);
579                        });
580                };
581
582                if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
583                        $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
584                }else{
585                        _alsoResize(o.alsoResize);
586                }
587        },
588
589        stop: function (event, ui) {
590                var self = $(this).data("resizable"), o = self.options;
591
592                var _reset = function (exp) {
593                        $(exp).each(function() {
594                                var el = $(this);
595                                // reset position for Opera - no need to verify it was changed
596                                el.css({ position: el.data("resizable-alsoresize").position });
597                        });
598                };
599
600                if (self._revertToRelativePosition) {
601                        self._revertToRelativePosition = false;
602                        if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
603                                $.each(o.alsoResize, function (exp) { _reset(exp); });
604                        }else{
605                                _reset(o.alsoResize);
606                        }
607                }
608
609                $(this).removeData("resizable-alsoresize");
610        }
611});
612
613$.ui.plugin.add("resizable", "animate", {
614
615        stop: function(event, ui) {
616                var self = $(this).data("resizable"), o = self.options;
617
618                var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
619                                        soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
620                                                soffsetw = ista ? 0 : self.sizeDiff.width;
621
622                var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
623                                        left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
624                                                top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
625
626                self.element.animate(
627                        $.extend(style, top && left ? { top: top, left: left } : {}), {
628                                duration: o.animateDuration,
629                                easing: o.animateEasing,
630                                step: function() {
631
632                                        var data = {
633                                                width: parseInt(self.element.css('width'), 10),
634                                                height: parseInt(self.element.css('height'), 10),
635                                                top: parseInt(self.element.css('top'), 10),
636                                                left: parseInt(self.element.css('left'), 10)
637                                        };
638
639                                        if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
640
641                                        // propagating resize, and updating values for each animation step
642                                        self._updateCache(data);
643                                        self._propagate("resize", event);
644
645                                }
646                        }
647                );
648        }
649
650});
651
652$.ui.plugin.add("resizable", "containment", {
653
654        start: function(event, ui) {
655                var self = $(this).data("resizable"), o = self.options, el = self.element;
656                var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
657                if (!ce) return;
658
659                self.containerElement = $(ce);
660
661                if (/document/.test(oc) || oc == document) {
662                        self.containerOffset = { left: 0, top: 0 };
663                        self.containerPosition = { left: 0, top: 0 };
664
665                        self.parentData = {
666                                element: $(document), left: 0, top: 0,
667                                width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
668                        };
669                }
670
671                // i'm a node, so compute top, left, right, bottom
672                else {
673                        var element = $(ce), p = [];
674                        $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
675
676                        self.containerOffset = element.offset();
677                        self.containerPosition = element.position();
678                        self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
679
680                        var co = self.containerOffset, ch = self.containerSize.height,  cw = self.containerSize.width,
681                                                width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
682
683                        self.parentData = {
684                                element: ce, left: co.left, top: co.top, width: width, height: height
685                        };
686                }
687        },
688
689        resize: function(event, ui) {
690                var self = $(this).data("resizable"), o = self.options,
691                                ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
692                                pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
693
694                if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
695
696                if (cp.left < (self._helper ? co.left : 0)) {
697                        self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
698                        if (pRatio) self.size.height = self.size.width / o.aspectRatio;
699                        self.position.left = o.helper ? co.left : 0;
700                }
701
702                if (cp.top < (self._helper ? co.top : 0)) {
703                        self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
704                        if (pRatio) self.size.width = self.size.height * o.aspectRatio;
705                        self.position.top = self._helper ? co.top : 0;
706                }
707
708                self.offset.left = self.parentData.left+self.position.left;
709                self.offset.top = self.parentData.top+self.position.top;
710
711                var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
712                                        hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
713
714                var isParent = self.containerElement.get(0) == self.element.parent().get(0),
715                    isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
716
717                if(isParent && isOffsetRelative) woset -= self.parentData.left;
718
719                if (woset + self.size.width >= self.parentData.width) {
720                        self.size.width = self.parentData.width - woset;
721                        if (pRatio) self.size.height = self.size.width / self.aspectRatio;
722                }
723
724                if (hoset + self.size.height >= self.parentData.height) {
725                        self.size.height = self.parentData.height - hoset;
726                        if (pRatio) self.size.width = self.size.height * self.aspectRatio;
727                }
728        },
729
730        stop: function(event, ui){
731                var self = $(this).data("resizable"), o = self.options, cp = self.position,
732                                co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
733
734                var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
735
736                if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
737                        $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
738
739                if (self._helper && !o.animate && (/static/).test(ce.css('position')))
740                        $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
741
742        }
743});
744
745$.ui.plugin.add("resizable", "ghost", {
746
747        start: function(event, ui) {
748
749                var self = $(this).data("resizable"), o = self.options, cs = self.size;
750
751                self.ghost = self.originalElement.clone();
752                self.ghost
753                        .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
754                        .addClass('ui-resizable-ghost')
755                        .addClass(typeof o.ghost == 'string' ? o.ghost : '');
756
757                self.ghost.appendTo(self.helper);
758
759        },
760
761        resize: function(event, ui){
762                var self = $(this).data("resizable"), o = self.options;
763                if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
764        },
765
766        stop: function(event, ui){
767                var self = $(this).data("resizable"), o = self.options;
768                if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
769        }
770
771});
772
773$.ui.plugin.add("resizable", "grid", {
774
775        resize: function(event, ui) {
776                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;
777                o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
778                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);
779
780                if (/^(se|s|e)$/.test(a)) {
781                        self.size.width = os.width + ox;
782                        self.size.height = os.height + oy;
783                }
784                else if (/^(ne)$/.test(a)) {
785                        self.size.width = os.width + ox;
786                        self.size.height = os.height + oy;
787                        self.position.top = op.top - oy;
788                }
789                else if (/^(sw)$/.test(a)) {
790                        self.size.width = os.width + ox;
791                        self.size.height = os.height + oy;
792                        self.position.left = op.left - ox;
793                }
794                else {
795                        self.size.width = os.width + ox;
796                        self.size.height = os.height + oy;
797                        self.position.top = op.top - oy;
798                        self.position.left = op.left - ox;
799                }
800        }
801
802});
803
804var num = function(v) {
805        return parseInt(v, 10) || 0;
806};
807
808var isNumber = function(value) {
809        return !isNaN(parseInt(value, 10));
810};
811
812})(jQuery);
Note: See TracBrowser for help on using the repository browser.