➔ $.widget(ꞌui.resizableꞌ)._mouseStop   F
last analyzed

Complexity

Conditions 9
Paths 514

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 514
nop 1
dl 0
loc 47
rs 3.4936
c 0
b 0
f 0
1
/*!
2
 * jQuery UI Resizable 1.12.1
3
 * http://jqueryui.com
4
 *
5
 * Copyright jQuery Foundation and other contributors
6
 * Released under the MIT license.
7
 * http://jquery.org/license
8
 */
9
10
//>>label: Resizable
11
//>>group: Interactions
12
//>>description: Enables resize functionality for any element.
13
//>>docs: http://api.jqueryui.com/resizable/
14
//>>demos: http://jqueryui.com/resizable/
15
//>>css.structure: ../../themes/base/core.css
16
//>>css.structure: ../../themes/base/resizable.css
17
//>>css.theme: ../../themes/base/theme.css
18
19
( function( factory ) {
20
	if ( typeof define === "function" && define.amd ) {
21
22
		// AMD. Register as an anonymous module.
23
		define( [
24
			"jquery",
25
			"./mouse",
26
			"../disable-selection",
27
			"../plugin",
28
			"../version",
29
			"../widget"
30
		], factory );
31
	} else {
32
33
		// Browser globals
34
		factory( jQuery );
35
	}
36
}( function( $ ) {
37
38
$.widget( "ui.resizable", $.ui.mouse, {
39
	version: "1.12.1",
40
	widgetEventPrefix: "resize",
41
	options: {
42
		alsoResize: false,
43
		animate: false,
44
		animateDuration: "slow",
45
		animateEasing: "swing",
46
		aspectRatio: false,
47
		autoHide: false,
48
		classes: {
49
			"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
50
		},
51
		containment: false,
52
		ghost: false,
53
		grid: false,
54
		handles: "e,s,se",
55
		helper: false,
56
		maxHeight: null,
57
		maxWidth: null,
58
		minHeight: 10,
59
		minWidth: 10,
60
61
		// See #7960
62
		zIndex: 90,
63
64
		// Callbacks
65
		resize: null,
66
		start: null,
67
		stop: null
68
	},
69
70
	_num: function( value ) {
71
		return parseFloat( value ) || 0;
72
	},
73
74
	_isNumber: function( value ) {
75
		return !isNaN( parseFloat( value ) );
76
	},
77
78
	_hasScroll: function( el, a ) {
79
80
		if ( $( el ).css( "overflow" ) === "hidden" ) {
81
			return false;
82
		}
83
84
		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
85
			has = false;
0 ignored issues
show
Unused Code introduced by
The assignment to variable has seems to be never used. Consider removing it.
Loading history...
86
87
		if ( el[ scroll ] > 0 ) {
88
			return true;
89
		}
90
91
		// TODO: determine which cases actually cause this to happen
92
		// if the element doesn't have the scroll set, see if it's possible to
93
		// set the scroll
94
		el[ scroll ] = 1;
95
		has = ( el[ scroll ] > 0 );
96
		el[ scroll ] = 0;
97
		return has;
98
	},
99
100
	_create: function() {
101
102
		var margins,
103
			o = this.options,
104
			that = this;
105
		this._addClass( "ui-resizable" );
106
107
		$.extend( this, {
108
			_aspectRatio: !!( o.aspectRatio ),
109
			aspectRatio: o.aspectRatio,
110
			originalElement: this.element,
111
			_proportionallyResizeElements: [],
112
			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
113
		} );
114
115
		// Wrap the element if it cannot hold child nodes
116
		if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
117
118
			this.element.wrap(
119
				$( "<div class='ui-wrapper' style='overflow: hidden;'></div>" ).css( {
120
					position: this.element.css( "position" ),
121
					width: this.element.outerWidth(),
122
					height: this.element.outerHeight(),
123
					top: this.element.css( "top" ),
124
					left: this.element.css( "left" )
125
				} )
126
			);
127
128
			this.element = this.element.parent().data(
129
				"ui-resizable", this.element.resizable( "instance" )
130
			);
131
132
			this.elementIsWrapper = true;
133
134
			margins = {
135
				marginTop: this.originalElement.css( "marginTop" ),
136
				marginRight: this.originalElement.css( "marginRight" ),
137
				marginBottom: this.originalElement.css( "marginBottom" ),
138
				marginLeft: this.originalElement.css( "marginLeft" )
139
			};
140
141
			this.element.css( margins );
142
			this.originalElement.css( "margin", 0 );
143
144
			// support: Safari
145
			// Prevent Safari textarea resize
146
			this.originalResizeStyle = this.originalElement.css( "resize" );
147
			this.originalElement.css( "resize", "none" );
148
149
			this._proportionallyResizeElements.push( this.originalElement.css( {
150
				position: "static",
151
				zoom: 1,
152
				display: "block"
153
			} ) );
154
155
			// Support: IE9
156
			// avoid IE jump (hard set the margin)
157
			this.originalElement.css( margins );
158
159
			this._proportionallyResize();
160
		}
161
162
		this._setupHandles();
163
164
		if ( o.autoHide ) {
165
			$( this.element )
166
				.on( "mouseenter", function() {
167
					if ( o.disabled ) {
168
						return;
169
					}
170
					that._removeClass( "ui-resizable-autohide" );
171
					that._handles.show();
172
				} )
173
				.on( "mouseleave", function() {
174
					if ( o.disabled ) {
175
						return;
176
					}
177
					if ( !that.resizing ) {
178
						that._addClass( "ui-resizable-autohide" );
179
						that._handles.hide();
180
					}
181
				} );
182
		}
183
184
		this._mouseInit();
185
	},
186
187
	_destroy: function() {
188
189
		this._mouseDestroy();
190
191
		var wrapper,
192
			_destroy = function( exp ) {
193
				$( exp )
194
					.removeData( "resizable" )
195
					.removeData( "ui-resizable" )
196
					.off( ".resizable" )
197
					.find( ".ui-resizable-handle" )
198
						.remove();
199
			};
200
201
		// TODO: Unwrap at same DOM position
202
		if ( this.elementIsWrapper ) {
203
			_destroy( this.element );
204
			wrapper = this.element;
205
			this.originalElement.css( {
206
				position: wrapper.css( "position" ),
207
				width: wrapper.outerWidth(),
208
				height: wrapper.outerHeight(),
209
				top: wrapper.css( "top" ),
210
				left: wrapper.css( "left" )
211
			} ).insertAfter( wrapper );
212
			wrapper.remove();
213
		}
214
215
		this.originalElement.css( "resize", this.originalResizeStyle );
216
		_destroy( this.originalElement );
217
218
		return this;
219
	},
220
221
	_setOption: function( key, value ) {
222
		this._super( key, value );
223
224
		switch ( key ) {
225
		case "handles":
226
			this._removeHandles();
227
			this._setupHandles();
228
			break;
229
		default:
230
			break;
231
		}
232
	},
233
234
	_setupHandles: function() {
235
		var o = this.options, handle, i, n, hname, axis, that = this;
236
		this.handles = o.handles ||
237
			( !$( ".ui-resizable-handle", this.element ).length ?
238
				"e,s,se" : {
239
					n: ".ui-resizable-n",
240
					e: ".ui-resizable-e",
241
					s: ".ui-resizable-s",
242
					w: ".ui-resizable-w",
243
					se: ".ui-resizable-se",
244
					sw: ".ui-resizable-sw",
245
					ne: ".ui-resizable-ne",
246
					nw: ".ui-resizable-nw"
247
				} );
248
249
		this._handles = $();
250
		if ( this.handles.constructor === String ) {
251
252
			if ( this.handles === "all" ) {
253
				this.handles = "n,e,s,w,se,sw,ne,nw";
254
			}
255
256
			n = this.handles.split( "," );
257
			this.handles = {};
258
259
			for ( i = 0; i < n.length; i++ ) {
260
261
				handle = $.trim( n[ i ] );
262
				hname = "ui-resizable-" + handle;
263
				axis = $( "<div>" );
264
				this._addClass( axis, "ui-resizable-handle " + hname );
265
266
				axis.css( { zIndex: o.zIndex } );
267
268
				this.handles[ handle ] = ".ui-resizable-" + handle;
269
				this.element.append( axis );
270
			}
271
272
		}
273
274
		this._renderAxis = function( target ) {
275
276
			var i, axis, padPos, padWrapper;
277
278
			target = target || this.element;
279
280
			for ( i in this.handles ) {
281
282
				if ( this.handles[ i ].constructor === String ) {
283
					this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
284
				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
285
					this.handles[ i ] = $( this.handles[ i ] );
286
					this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
287
				}
288
289
				if ( this.elementIsWrapper &&
290
						this.originalElement[ 0 ]
291
							.nodeName
292
							.match( /^(textarea|input|select|button)$/i ) ) {
293
					axis = $( this.handles[ i ], this.element );
294
295
					padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
296
						axis.outerHeight() :
297
						axis.outerWidth();
298
299
					padPos = [ "padding",
300
						/ne|nw|n/.test( i ) ? "Top" :
301
						/se|sw|s/.test( i ) ? "Bottom" :
302
						/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
303
304
					target.css( padPos, padWrapper );
305
306
					this._proportionallyResize();
307
				}
308
309
				this._handles = this._handles.add( this.handles[ i ] );
310
			}
311
		};
312
313
		// TODO: make renderAxis a prototype function
314
		this._renderAxis( this.element );
315
316
		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
317
		this._handles.disableSelection();
318
319
		this._handles.on( "mouseover", function() {
320
			if ( !that.resizing ) {
321
				if ( this.className ) {
322
					axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
323
				}
324
				that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
0 ignored issues
show
Bug introduced by
The variable axis seems to not be initialized for all possible execution paths.
Loading history...
325
			}
326
		} );
327
328
		if ( o.autoHide ) {
329
			this._handles.hide();
330
			this._addClass( "ui-resizable-autohide" );
331
		}
332
	},
333
334
	_removeHandles: function() {
335
		this._handles.remove();
336
	},
337
338
	_mouseCapture: function( event ) {
339
		var i, handle,
340
			capture = false;
341
342
		for ( i in this.handles ) {
343
			handle = $( this.handles[ i ] )[ 0 ];
344
			if ( handle === event.target || $.contains( handle, event.target ) ) {
345
				capture = true;
346
			}
347
		}
348
349
		return !this.options.disabled && capture;
350
	},
351
352
	_mouseStart: function( event ) {
353
354
		var curleft, curtop, cursor,
355
			o = this.options,
356
			el = this.element;
357
358
		this.resizing = true;
359
360
		this._renderProxy();
361
362
		curleft = this._num( this.helper.css( "left" ) );
363
		curtop = this._num( this.helper.css( "top" ) );
364
365
		if ( o.containment ) {
366
			curleft += $( o.containment ).scrollLeft() || 0;
367
			curtop += $( o.containment ).scrollTop() || 0;
368
		}
369
370
		this.offset = this.helper.offset();
371
		this.position = { left: curleft, top: curtop };
372
373
		this.size = this._helper ? {
374
				width: this.helper.width(),
375
				height: this.helper.height()
376
			} : {
377
				width: el.width(),
378
				height: el.height()
379
			};
380
381
		this.originalSize = this._helper ? {
382
				width: el.outerWidth(),
383
				height: el.outerHeight()
384
			} : {
385
				width: el.width(),
386
				height: el.height()
387
			};
388
389
		this.sizeDiff = {
390
			width: el.outerWidth() - el.width(),
391
			height: el.outerHeight() - el.height()
392
		};
393
394
		this.originalPosition = { left: curleft, top: curtop };
395
		this.originalMousePosition = { left: event.pageX, top: event.pageY };
396
397
		this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
398
			o.aspectRatio :
399
			( ( this.originalSize.width / this.originalSize.height ) || 1 );
400
401
		cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
402
		$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
403
404
		this._addClass( "ui-resizable-resizing" );
405
		this._propagate( "start", event );
406
		return true;
407
	},
408
409
	_mouseDrag: function( event ) {
410
411
		var data, props,
412
			smp = this.originalMousePosition,
413
			a = this.axis,
414
			dx = ( event.pageX - smp.left ) || 0,
415
			dy = ( event.pageY - smp.top ) || 0,
416
			trigger = this._change[ a ];
417
418
		this._updatePrevProperties();
419
420
		if ( !trigger ) {
421
			return false;
422
		}
423
424
		data = trigger.apply( this, [ event, dx, dy ] );
425
426
		this._updateVirtualBoundaries( event.shiftKey );
427
		if ( this._aspectRatio || event.shiftKey ) {
428
			data = this._updateRatio( data, event );
429
		}
430
431
		data = this._respectSize( data, event );
432
433
		this._updateCache( data );
434
435
		this._propagate( "resize", event );
436
437
		props = this._applyChanges();
438
439
		if ( !this._helper && this._proportionallyResizeElements.length ) {
440
			this._proportionallyResize();
441
		}
442
443
		if ( !$.isEmptyObject( props ) ) {
444
			this._updatePrevProperties();
445
			this._trigger( "resize", event, this.ui() );
446
			this._applyChanges();
447
		}
448
449
		return false;
450
	},
451
452
	_mouseStop: function( event ) {
453
454
		this.resizing = false;
455
		var pr, ista, soffseth, soffsetw, s, left, top,
456
			o = this.options, that = this;
457
458
		if ( this._helper ) {
459
460
			pr = this._proportionallyResizeElements;
461
			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
462
			soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
463
			soffsetw = ista ? 0 : that.sizeDiff.width;
464
465
			s = {
466
				width: ( that.helper.width()  - soffsetw ),
467
				height: ( that.helper.height() - soffseth )
468
			};
469
			left = ( parseFloat( that.element.css( "left" ) ) +
470
				( that.position.left - that.originalPosition.left ) ) || null;
471
			top = ( parseFloat( that.element.css( "top" ) ) +
472
				( that.position.top - that.originalPosition.top ) ) || null;
473
474
			if ( !o.animate ) {
475
				this.element.css( $.extend( s, { top: top, left: left } ) );
476
			}
477
478
			that.helper.height( that.size.height );
479
			that.helper.width( that.size.width );
480
481
			if ( this._helper && !o.animate ) {
482
				this._proportionallyResize();
483
			}
484
		}
485
486
		$( "body" ).css( "cursor", "auto" );
487
488
		this._removeClass( "ui-resizable-resizing" );
489
490
		this._propagate( "stop", event );
491
492
		if ( this._helper ) {
493
			this.helper.remove();
494
		}
495
496
		return false;
497
498
	},
499
500
	_updatePrevProperties: function() {
501
		this.prevPosition = {
502
			top: this.position.top,
503
			left: this.position.left
504
		};
505
		this.prevSize = {
506
			width: this.size.width,
507
			height: this.size.height
508
		};
509
	},
510
511
	_applyChanges: function() {
512
		var props = {};
513
514
		if ( this.position.top !== this.prevPosition.top ) {
515
			props.top = this.position.top + "px";
516
		}
517
		if ( this.position.left !== this.prevPosition.left ) {
518
			props.left = this.position.left + "px";
519
		}
520
		if ( this.size.width !== this.prevSize.width ) {
521
			props.width = this.size.width + "px";
522
		}
523
		if ( this.size.height !== this.prevSize.height ) {
524
			props.height = this.size.height + "px";
525
		}
526
527
		this.helper.css( props );
528
529
		return props;
530
	},
531
532
	_updateVirtualBoundaries: function( forceAspectRatio ) {
533
		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
534
			o = this.options;
535
536
		b = {
537
			minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
538
			maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
539
			minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
540
			maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
541
		};
542
543
		if ( this._aspectRatio || forceAspectRatio ) {
544
			pMinWidth = b.minHeight * this.aspectRatio;
545
			pMinHeight = b.minWidth / this.aspectRatio;
546
			pMaxWidth = b.maxHeight * this.aspectRatio;
547
			pMaxHeight = b.maxWidth / this.aspectRatio;
548
549
			if ( pMinWidth > b.minWidth ) {
550
				b.minWidth = pMinWidth;
551
			}
552
			if ( pMinHeight > b.minHeight ) {
553
				b.minHeight = pMinHeight;
554
			}
555
			if ( pMaxWidth < b.maxWidth ) {
556
				b.maxWidth = pMaxWidth;
557
			}
558
			if ( pMaxHeight < b.maxHeight ) {
559
				b.maxHeight = pMaxHeight;
560
			}
561
		}
562
		this._vBoundaries = b;
563
	},
564
565
	_updateCache: function( data ) {
566
		this.offset = this.helper.offset();
567
		if ( this._isNumber( data.left ) ) {
568
			this.position.left = data.left;
569
		}
570
		if ( this._isNumber( data.top ) ) {
571
			this.position.top = data.top;
572
		}
573
		if ( this._isNumber( data.height ) ) {
574
			this.size.height = data.height;
575
		}
576
		if ( this._isNumber( data.width ) ) {
577
			this.size.width = data.width;
578
		}
579
	},
580
581
	_updateRatio: function( data ) {
582
583
		var cpos = this.position,
584
			csize = this.size,
585
			a = this.axis;
586
587
		if ( this._isNumber( data.height ) ) {
588
			data.width = ( data.height * this.aspectRatio );
589
		} else if ( this._isNumber( data.width ) ) {
590
			data.height = ( data.width / this.aspectRatio );
591
		}
592
593
		if ( a === "sw" ) {
594
			data.left = cpos.left + ( csize.width - data.width );
595
			data.top = null;
596
		}
597
		if ( a === "nw" ) {
598
			data.top = cpos.top + ( csize.height - data.height );
599
			data.left = cpos.left + ( csize.width - data.width );
600
		}
601
602
		return data;
603
	},
604
605
	_respectSize: function( data ) {
606
607
		var o = this._vBoundaries,
608
			a = this.axis,
609
			ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
610
			ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
611
			isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
612
			isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
613
			dw = this.originalPosition.left + this.originalSize.width,
614
			dh = this.originalPosition.top + this.originalSize.height,
615
			cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
616
		if ( isminw ) {
617
			data.width = o.minWidth;
618
		}
619
		if ( isminh ) {
620
			data.height = o.minHeight;
621
		}
622
		if ( ismaxw ) {
623
			data.width = o.maxWidth;
624
		}
625
		if ( ismaxh ) {
626
			data.height = o.maxHeight;
627
		}
628
629
		if ( isminw && cw ) {
630
			data.left = dw - o.minWidth;
631
		}
632
		if ( ismaxw && cw ) {
633
			data.left = dw - o.maxWidth;
634
		}
635
		if ( isminh && ch ) {
636
			data.top = dh - o.minHeight;
637
		}
638
		if ( ismaxh && ch ) {
639
			data.top = dh - o.maxHeight;
640
		}
641
642
		// Fixing jump error on top/left - bug #2330
643
		if ( !data.width && !data.height && !data.left && data.top ) {
644
			data.top = null;
645
		} else if ( !data.width && !data.height && !data.top && data.left ) {
646
			data.left = null;
647
		}
648
649
		return data;
650
	},
651
652
	_getPaddingPlusBorderDimensions: function( element ) {
653
		var i = 0,
654
			widths = [],
655
			borders = [
656
				element.css( "borderTopWidth" ),
657
				element.css( "borderRightWidth" ),
658
				element.css( "borderBottomWidth" ),
659
				element.css( "borderLeftWidth" )
660
			],
661
			paddings = [
662
				element.css( "paddingTop" ),
663
				element.css( "paddingRight" ),
664
				element.css( "paddingBottom" ),
665
				element.css( "paddingLeft" )
666
			];
667
668
		for ( ; i < 4; i++ ) {
669
			widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
670
			widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
671
		}
672
673
		return {
674
			height: widths[ 0 ] + widths[ 2 ],
675
			width: widths[ 1 ] + widths[ 3 ]
676
		};
677
	},
678
679
	_proportionallyResize: function() {
680
681
		if ( !this._proportionallyResizeElements.length ) {
682
			return;
683
		}
684
685
		var prel,
686
			i = 0,
687
			element = this.helper || this.element;
688
689
		for ( ; i < this._proportionallyResizeElements.length; i++ ) {
690
691
			prel = this._proportionallyResizeElements[ i ];
692
693
			// TODO: Seems like a bug to cache this.outerDimensions
694
			// considering that we are in a loop.
695
			if ( !this.outerDimensions ) {
696
				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
697
			}
698
699
			prel.css( {
700
				height: ( element.height() - this.outerDimensions.height ) || 0,
701
				width: ( element.width() - this.outerDimensions.width ) || 0
702
			} );
703
704
		}
705
706
	},
707
708
	_renderProxy: function() {
709
710
		var el = this.element, o = this.options;
711
		this.elementOffset = el.offset();
712
713
		if ( this._helper ) {
714
715
			this.helper = this.helper || $( "<div style='overflow:hidden;'></div>" );
716
717
			this._addClass( this.helper, this._helper );
718
			this.helper.css( {
719
				width: this.element.outerWidth(),
720
				height: this.element.outerHeight(),
721
				position: "absolute",
722
				left: this.elementOffset.left + "px",
723
				top: this.elementOffset.top + "px",
724
				zIndex: ++o.zIndex //TODO: Don't modify option
725
			} );
726
727
			this.helper
728
				.appendTo( "body" )
729
				.disableSelection();
730
731
		} else {
732
			this.helper = this.element;
733
		}
734
735
	},
736
737
	_change: {
738
		e: function( event, dx ) {
739
			return { width: this.originalSize.width + dx };
740
		},
741
		w: function( event, dx ) {
742
			var cs = this.originalSize, sp = this.originalPosition;
743
			return { left: sp.left + dx, width: cs.width - dx };
744
		},
745
		n: function( event, dx, dy ) {
746
			var cs = this.originalSize, sp = this.originalPosition;
747
			return { top: sp.top + dy, height: cs.height - dy };
748
		},
749
		s: function( event, dx, dy ) {
750
			return { height: this.originalSize.height + dy };
751
		},
752
		se: function( event, dx, dy ) {
753
			return $.extend( this._change.s.apply( this, arguments ),
754
				this._change.e.apply( this, [ event, dx, dy ] ) );
755
		},
756
		sw: function( event, dx, dy ) {
757
			return $.extend( this._change.s.apply( this, arguments ),
758
				this._change.w.apply( this, [ event, dx, dy ] ) );
759
		},
760
		ne: function( event, dx, dy ) {
761
			return $.extend( this._change.n.apply( this, arguments ),
762
				this._change.e.apply( this, [ event, dx, dy ] ) );
763
		},
764
		nw: function( event, dx, dy ) {
765
			return $.extend( this._change.n.apply( this, arguments ),
766
				this._change.w.apply( this, [ event, dx, dy ] ) );
767
		}
768
	},
769
770
	_propagate: function( n, event ) {
771
		$.ui.plugin.call( this, n, [ event, this.ui() ] );
772
		( n !== "resize" && this._trigger( n, event, this.ui() ) );
773
	},
774
775
	plugins: {},
776
777
	ui: function() {
778
		return {
779
			originalElement: this.originalElement,
780
			element: this.element,
781
			helper: this.helper,
782
			position: this.position,
783
			size: this.size,
784
			originalSize: this.originalSize,
785
			originalPosition: this.originalPosition
786
		};
787
	}
788
789
} );
790
791
/*
792
 * Resizable Extensions
793
 */
794
795
$.ui.plugin.add( "resizable", "animate", {
796
797 View Code Duplication
	stop: function( event ) {
798
		var that = $( this ).resizable( "instance" ),
799
			o = that.options,
800
			pr = that._proportionallyResizeElements,
801
			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
802
			soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
803
			soffsetw = ista ? 0 : that.sizeDiff.width,
804
			style = {
805
				width: ( that.size.width - soffsetw ),
806
				height: ( that.size.height - soffseth )
807
			},
808
			left = ( parseFloat( that.element.css( "left" ) ) +
809
				( that.position.left - that.originalPosition.left ) ) || null,
810
			top = ( parseFloat( that.element.css( "top" ) ) +
811
				( that.position.top - that.originalPosition.top ) ) || null;
812
813
		that.element.animate(
814
			$.extend( style, top && left ? { top: top, left: left } : {} ), {
815
				duration: o.animateDuration,
816
				easing: o.animateEasing,
817
				step: function() {
818
819
					var data = {
820
						width: parseFloat( that.element.css( "width" ) ),
821
						height: parseFloat( that.element.css( "height" ) ),
822
						top: parseFloat( that.element.css( "top" ) ),
823
						left: parseFloat( that.element.css( "left" ) )
824
					};
825
826
					if ( pr && pr.length ) {
827
						$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
828
					}
829
830
					// Propagating resize, and updating values for each animation step
831
					that._updateCache( data );
832
					that._propagate( "resize", event );
833
834
				}
835
			}
836
		);
837
	}
838
839
} );
840
841
$.ui.plugin.add( "resizable", "containment", {
842
843
	start: function() {
844
		var element, p, co, ch, cw, width, height,
845
			that = $( this ).resizable( "instance" ),
846
			o = that.options,
847
			el = that.element,
848
			oc = o.containment,
849
			ce = ( oc instanceof $ ) ?
850
				oc.get( 0 ) :
851
				( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
852
853
		if ( !ce ) {
854
			return;
855
		}
856
857
		that.containerElement = $( ce );
858
859
		if ( /document/.test( oc ) || oc === document ) {
860
			that.containerOffset = {
861
				left: 0,
862
				top: 0
863
			};
864
			that.containerPosition = {
865
				left: 0,
866
				top: 0
867
			};
868
869
			that.parentData = {
870
				element: $( document ),
871
				left: 0,
872
				top: 0,
873
				width: $( document ).width(),
874
				height: $( document ).height() || document.body.parentNode.scrollHeight
875
			};
876
		} else {
877
			element = $( ce );
878
			p = [];
879
			$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
880
				p[ i ] = that._num( element.css( "padding" + name ) );
881
			} );
882
883
			that.containerOffset = element.offset();
884
			that.containerPosition = element.position();
885
			that.containerSize = {
886
				height: ( element.innerHeight() - p[ 3 ] ),
887
				width: ( element.innerWidth() - p[ 1 ] )
888
			};
889
890
			co = that.containerOffset;
891
			ch = that.containerSize.height;
892
			cw = that.containerSize.width;
893
			width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
894
			height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
895
896
			that.parentData = {
897
				element: ce,
898
				left: co.left,
899
				top: co.top,
900
				width: width,
901
				height: height
902
			};
903
		}
904
	},
905
906
	resize: function( event ) {
907
		var woset, hoset, isParent, isOffsetRelative,
908
			that = $( this ).resizable( "instance" ),
909
			o = that.options,
910
			co = that.containerOffset,
911
			cp = that.position,
912
			pRatio = that._aspectRatio || event.shiftKey,
913
			cop = {
914
				top: 0,
915
				left: 0
916
			},
917
			ce = that.containerElement,
918
			continueResize = true;
919
920
		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
921
			cop = co;
922
		}
923
924
		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
925
			that.size.width = that.size.width +
926
				( that._helper ?
927
					( that.position.left - co.left ) :
928
					( that.position.left - cop.left ) );
929
930
			if ( pRatio ) {
931
				that.size.height = that.size.width / that.aspectRatio;
932
				continueResize = false;
933
			}
934
			that.position.left = o.helper ? co.left : 0;
935
		}
936
937
		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
938
			that.size.height = that.size.height +
939
				( that._helper ?
940
					( that.position.top - co.top ) :
941
					that.position.top );
942
943
			if ( pRatio ) {
944
				that.size.width = that.size.height * that.aspectRatio;
945
				continueResize = false;
946
			}
947
			that.position.top = that._helper ? co.top : 0;
948
		}
949
950
		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
951
		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
952
953
		if ( isParent && isOffsetRelative ) {
954
			that.offset.left = that.parentData.left + that.position.left;
955
			that.offset.top = that.parentData.top + that.position.top;
956
		} else {
957
			that.offset.left = that.element.offset().left;
958
			that.offset.top = that.element.offset().top;
959
		}
960
961
		woset = Math.abs( that.sizeDiff.width +
962
			( that._helper ?
963
				that.offset.left - cop.left :
964
				( that.offset.left - co.left ) ) );
965
966
		hoset = Math.abs( that.sizeDiff.height +
967
			( that._helper ?
968
				that.offset.top - cop.top :
969
				( that.offset.top - co.top ) ) );
970
971
		if ( woset + that.size.width >= that.parentData.width ) {
972
			that.size.width = that.parentData.width - woset;
973
			if ( pRatio ) {
974
				that.size.height = that.size.width / that.aspectRatio;
975
				continueResize = false;
976
			}
977
		}
978
979
		if ( hoset + that.size.height >= that.parentData.height ) {
980
			that.size.height = that.parentData.height - hoset;
981
			if ( pRatio ) {
982
				that.size.width = that.size.height * that.aspectRatio;
983
				continueResize = false;
984
			}
985
		}
986
987
		if ( !continueResize ) {
988
			that.position.left = that.prevPosition.left;
989
			that.position.top = that.prevPosition.top;
990
			that.size.width = that.prevSize.width;
991
			that.size.height = that.prevSize.height;
992
		}
993
	},
994
995
	stop: function() {
996
		var that = $( this ).resizable( "instance" ),
997
			o = that.options,
998
			co = that.containerOffset,
999
			cop = that.containerPosition,
1000
			ce = that.containerElement,
1001
			helper = $( that.helper ),
1002
			ho = helper.offset(),
1003
			w = helper.outerWidth() - that.sizeDiff.width,
1004
			h = helper.outerHeight() - that.sizeDiff.height;
1005
1006
		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
1007
			$( this ).css( {
1008
				left: ho.left - cop.left - co.left,
1009
				width: w,
1010
				height: h
1011
			} );
1012
		}
1013
1014
		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
1015
			$( this ).css( {
1016
				left: ho.left - cop.left - co.left,
1017
				width: w,
1018
				height: h
1019
			} );
1020
		}
1021
	}
1022
} );
1023
1024
$.ui.plugin.add( "resizable", "alsoResize", {
1025
1026
	start: function() {
1027
		var that = $( this ).resizable( "instance" ),
1028
			o = that.options;
1029
1030
		$( o.alsoResize ).each( function() {
1031
			var el = $( this );
1032
			el.data( "ui-resizable-alsoresize", {
1033
				width: parseFloat( el.width() ), height: parseFloat( el.height() ),
1034
				left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
1035
			} );
1036
		} );
1037
	},
1038
1039
	resize: function( event, ui ) {
1040
		var that = $( this ).resizable( "instance" ),
1041
			o = that.options,
1042
			os = that.originalSize,
1043
			op = that.originalPosition,
1044
			delta = {
1045
				height: ( that.size.height - os.height ) || 0,
1046
				width: ( that.size.width - os.width ) || 0,
1047
				top: ( that.position.top - op.top ) || 0,
1048
				left: ( that.position.left - op.left ) || 0
1049
			};
1050
1051
			$( o.alsoResize ).each( function() {
1052
				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
1053
					css = el.parents( ui.originalElement[ 0 ] ).length ?
1054
							[ "width", "height" ] :
1055
							[ "width", "height", "top", "left" ];
1056
1057
				$.each( css, function( i, prop ) {
1058
					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
1059
					if ( sum && sum >= 0 ) {
1060
						style[ prop ] = sum || null;
1061
					}
1062
				} );
1063
1064
				el.css( style );
1065
			} );
1066
	},
1067
1068
	stop: function() {
1069
		$( this ).removeData( "ui-resizable-alsoresize" );
1070
	}
1071
} );
1072
1073
$.ui.plugin.add( "resizable", "ghost", {
1074
1075
	start: function() {
1076
1077
		var that = $( this ).resizable( "instance" ), cs = that.size;
1078
1079
		that.ghost = that.originalElement.clone();
1080
		that.ghost.css( {
1081
			opacity: 0.25,
1082
			display: "block",
1083
			position: "relative",
1084
			height: cs.height,
1085
			width: cs.width,
1086
			margin: 0,
1087
			left: 0,
1088
			top: 0
1089
		} );
1090
1091
		that._addClass( that.ghost, "ui-resizable-ghost" );
1092
1093
		// DEPRECATED
1094
		// TODO: remove after 1.12
1095
		if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
1096
1097
			// Ghost option
1098
			that.ghost.addClass( this.options.ghost );
1099
		}
1100
1101
		that.ghost.appendTo( that.helper );
1102
1103
	},
1104
1105
	resize: function() {
1106
		var that = $( this ).resizable( "instance" );
1107
		if ( that.ghost ) {
1108
			that.ghost.css( {
1109
				position: "relative",
1110
				height: that.size.height,
1111
				width: that.size.width
1112
			} );
1113
		}
1114
	},
1115
1116
	stop: function() {
1117
		var that = $( this ).resizable( "instance" );
1118
		if ( that.ghost && that.helper ) {
1119
			that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
1120
		}
1121
	}
1122
1123
} );
1124
1125
$.ui.plugin.add( "resizable", "grid", {
1126
1127
	resize: function() {
1128
		var outerDimensions,
1129
			that = $( this ).resizable( "instance" ),
1130
			o = that.options,
1131
			cs = that.size,
1132
			os = that.originalSize,
1133
			op = that.originalPosition,
1134
			a = that.axis,
1135
			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
1136
			gridX = ( grid[ 0 ] || 1 ),
1137
			gridY = ( grid[ 1 ] || 1 ),
1138
			ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
1139
			oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
1140
			newWidth = os.width + ox,
1141
			newHeight = os.height + oy,
1142
			isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
1143
			isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
1144
			isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
1145
			isMinHeight = o.minHeight && ( o.minHeight > newHeight );
1146
1147
		o.grid = grid;
1148
1149
		if ( isMinWidth ) {
1150
			newWidth += gridX;
1151
		}
1152
		if ( isMinHeight ) {
1153
			newHeight += gridY;
1154
		}
1155
		if ( isMaxWidth ) {
1156
			newWidth -= gridX;
1157
		}
1158
		if ( isMaxHeight ) {
1159
			newHeight -= gridY;
1160
		}
1161
1162
		if ( /^(se|s|e)$/.test( a ) ) {
1163
			that.size.width = newWidth;
1164
			that.size.height = newHeight;
1165
		} else if ( /^(ne)$/.test( a ) ) {
1166
			that.size.width = newWidth;
1167
			that.size.height = newHeight;
1168
			that.position.top = op.top - oy;
1169
		} else if ( /^(sw)$/.test( a ) ) {
1170
			that.size.width = newWidth;
1171
			that.size.height = newHeight;
1172
			that.position.left = op.left - ox;
1173
		} else {
1174
			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
1175
				outerDimensions = that._getPaddingPlusBorderDimensions( this );
1176
			}
1177
1178
			if ( newHeight - gridY > 0 ) {
1179
				that.size.height = newHeight;
1180
				that.position.top = op.top - oy;
1181
			} else {
1182
				newHeight = gridY - outerDimensions.height;
0 ignored issues
show
Bug introduced by
The variable outerDimensions does not seem to be initialized in case newHeight - gridY <= 0 || newWidth - gridX <= 0 on line 1174 is false. Are you sure this can never be the case?
Loading history...
1183
				that.size.height = newHeight;
1184
				that.position.top = op.top + os.height - newHeight;
1185
			}
1186
			if ( newWidth - gridX > 0 ) {
1187
				that.size.width = newWidth;
1188
				that.position.left = op.left - ox;
1189
			} else {
1190
				newWidth = gridX - outerDimensions.width;
1191
				that.size.width = newWidth;
1192
				that.position.left = op.left + os.width - newWidth;
1193
			}
1194
		}
1195
	}
1196
1197
} );
1198
1199
return $.ui.resizable;
1200
1201
} ) );
1202