国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

771 lines
27KB

  1. /*
  2. * jQuery UI Resizable
  3. *
  4. * Copyright (c) 2008 Paul Bakaus
  5. * Dual licensed under the MIT (MIT-LICENSE.txt)
  6. * and GPL (GPL-LICENSE.txt) licenses.
  7. *
  8. * http://docs.jquery.com/UI/Resizables
  9. *
  10. * Depends:
  11. * ui.core.js
  12. */
  13. (function($) {
  14. $.widget("ui.resizable", $.extend({}, $.ui.mouse, {
  15. init: function() {
  16. var self = this, o = this.options;
  17. var elpos = this.element.css('position');
  18. this.originalElement = this.element;
  19. // simulate .ui-resizable { position: relative; }
  20. this.element.addClass("ui-resizable").css({ position: /static/.test(elpos) ? 'relative' : elpos });
  21. $.extend(o, {
  22. _aspectRatio: !!(o.aspectRatio),
  23. helper: o.helper || o.ghost || o.animate ? o.helper || 'proxy' : null,
  24. knobHandles: o.knobHandles === true ? 'ui-resizable-knob-handle' : o.knobHandles
  25. });
  26. //Default Theme
  27. var aBorder = '1px solid #DEDEDE';
  28. o.defaultTheme = {
  29. 'ui-resizable': { display: 'block' },
  30. 'ui-resizable-handle': { position: 'absolute', background: '#F2F2F2', fontSize: '0.1px' },
  31. 'ui-resizable-n': { cursor: 'n-resize', height: '4px', left: '0px', right: '0px', borderTop: aBorder },
  32. 'ui-resizable-s': { cursor: 's-resize', height: '4px', left: '0px', right: '0px', borderBottom: aBorder },
  33. 'ui-resizable-e': { cursor: 'e-resize', width: '4px', top: '0px', bottom: '0px', borderRight: aBorder },
  34. 'ui-resizable-w': { cursor: 'w-resize', width: '4px', top: '0px', bottom: '0px', borderLeft: aBorder },
  35. 'ui-resizable-se': { cursor: 'se-resize', width: '4px', height: '4px', borderRight: aBorder, borderBottom: aBorder },
  36. 'ui-resizable-sw': { cursor: 'sw-resize', width: '4px', height: '4px', borderBottom: aBorder, borderLeft: aBorder },
  37. 'ui-resizable-ne': { cursor: 'ne-resize', width: '4px', height: '4px', borderRight: aBorder, borderTop: aBorder },
  38. 'ui-resizable-nw': { cursor: 'nw-resize', width: '4px', height: '4px', borderLeft: aBorder, borderTop: aBorder }
  39. };
  40. o.knobTheme = {
  41. 'ui-resizable-handle': { background: '#F2F2F2', border: '1px solid #808080', height: '8px', width: '8px' },
  42. 'ui-resizable-n': { cursor: 'n-resize', top: '0px', left: '45%' },
  43. 'ui-resizable-s': { cursor: 's-resize', bottom: '0px', left: '45%' },
  44. 'ui-resizable-e': { cursor: 'e-resize', right: '0px', top: '45%' },
  45. 'ui-resizable-w': { cursor: 'w-resize', left: '0px', top: '45%' },
  46. 'ui-resizable-se': { cursor: 'se-resize', right: '0px', bottom: '0px' },
  47. 'ui-resizable-sw': { cursor: 'sw-resize', left: '0px', bottom: '0px' },
  48. 'ui-resizable-nw': { cursor: 'nw-resize', left: '0px', top: '0px' },
  49. 'ui-resizable-ne': { cursor: 'ne-resize', right: '0px', top: '0px' }
  50. };
  51. o._nodeName = this.element[0].nodeName;
  52. //Wrap the element if it cannot hold child nodes
  53. if(o._nodeName.match(/canvas|textarea|input|select|button|img/i)) {
  54. var el = this.element;
  55. //Opera fixing relative position
  56. if (/relative/.test(el.css('position')) && $.browser.opera)
  57. el.css({ position: 'relative', top: 'auto', left: 'auto' });
  58. //Create a wrapper element and set the wrapper to the new current internal element
  59. el.wrap(
  60. $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css( {
  61. position: el.css('position'),
  62. width: el.outerWidth(),
  63. height: el.outerHeight(),
  64. top: el.css('top'),
  65. left: el.css('left')
  66. })
  67. );
  68. var oel = this.element; this.element = this.element.parent();
  69. // store instance on wrapper
  70. this.element.data('resizable', this);
  71. //Move margins to the wrapper
  72. this.element.css({ marginLeft: oel.css("marginLeft"), marginTop: oel.css("marginTop"),
  73. marginRight: oel.css("marginRight"), marginBottom: oel.css("marginBottom")
  74. });
  75. oel.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
  76. //Prevent Safari textarea resize
  77. if ($.browser.safari && o.preventDefault) oel.css('resize', 'none');
  78. o.proportionallyResize = oel.css({ position: 'static', zoom: 1, display: 'block' });
  79. // avoid IE jump
  80. this.element.css({ margin: oel.css('margin') });
  81. // fix handlers offset
  82. this._proportionallyResize();
  83. }
  84. if(!o.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' };
  85. if(o.handles.constructor == String) {
  86. o.zIndex = o.zIndex || 1000;
  87. if(o.handles == 'all') o.handles = 'n,e,s,w,se,sw,ne,nw';
  88. var n = o.handles.split(","); o.handles = {};
  89. // insertions are applied when don't have theme loaded
  90. var insertionsDefault = {
  91. handle: 'position: absolute; display: none; overflow:hidden;',
  92. n: 'top: 0pt; width:100%;',
  93. e: 'right: 0pt; height:100%;',
  94. s: 'bottom: 0pt; width:100%;',
  95. w: 'left: 0pt; height:100%;',
  96. se: 'bottom: 0pt; right: 0px;',
  97. sw: 'bottom: 0pt; left: 0px;',
  98. ne: 'top: 0pt; right: 0px;',
  99. nw: 'top: 0pt; left: 0px;'
  100. };
  101. for(var i = 0; i < n.length; i++) {
  102. var handle = $.trim(n[i]), dt = o.defaultTheme, hname = 'ui-resizable-'+handle, loadDefault = !$.ui.css(hname) && !o.knobHandles, userKnobClass = $.ui.css('ui-resizable-knob-handle'),
  103. allDefTheme = $.extend(dt[hname], dt['ui-resizable-handle']), allKnobTheme = $.extend(o.knobTheme[hname], !userKnobClass ? o.knobTheme['ui-resizable-handle'] : {});
  104. // increase zIndex of sw, se, ne, nw axis
  105. var applyZIndex = /sw|se|ne|nw/.test(handle) ? { zIndex: ++o.zIndex } : {};
  106. var defCss = (loadDefault ? insertionsDefault[handle] : ''),
  107. axis = $(['<div class="ui-resizable-handle ', hname, '" style="', defCss, insertionsDefault.handle, '"></div>'].join('')).css( applyZIndex );
  108. o.handles[handle] = '.ui-resizable-'+handle;
  109. this.element.append(
  110. //Theme detection, if not loaded, load o.defaultTheme
  111. axis.css( loadDefault ? allDefTheme : {} )
  112. // Load the knobHandle css, fix width, height, top, left...
  113. .css( o.knobHandles ? allKnobTheme : {} ).addClass(o.knobHandles ? 'ui-resizable-knob-handle' : '').addClass(o.knobHandles)
  114. );
  115. }
  116. if (o.knobHandles) this.element.addClass('ui-resizable-knob').css( !$.ui.css('ui-resizable-knob') ? { /*border: '1px #fff dashed'*/ } : {} );
  117. }
  118. this._renderAxis = function(target) {
  119. target = target || this.element;
  120. for(var i in o.handles) {
  121. if(o.handles[i].constructor == String)
  122. o.handles[i] = $(o.handles[i], this.element).show();
  123. if (o.transparent)
  124. o.handles[i].css({opacity:0});
  125. //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
  126. if (this.element.is('.ui-wrapper') &&
  127. o._nodeName.match(/textarea|input|select|button/i)) {
  128. var axis = $(o.handles[i], this.element), padWrapper = 0;
  129. //Checking the correct pad and border
  130. padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
  131. //The padding type i have to apply...
  132. var padPos = [ 'padding',
  133. /ne|nw|n/.test(i) ? 'Top' :
  134. /se|sw|s/.test(i) ? 'Bottom' :
  135. /^e$/.test(i) ? 'Right' : 'Left' ].join("");
  136. if (!o.transparent)
  137. target.css(padPos, padWrapper);
  138. this._proportionallyResize();
  139. }
  140. if(!$(o.handles[i]).length) continue;
  141. }
  142. };
  143. this._renderAxis(this.element);
  144. o._handles = $('.ui-resizable-handle', self.element);
  145. if (o.disableSelection)
  146. o._handles.each(function(i, e) { $.ui.disableSelection(e); });
  147. //Matching axis name
  148. o._handles.mouseover(function() {
  149. if (!o.resizing) {
  150. if (this.className)
  151. var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
  152. //Axis, default = se
  153. self.axis = o.axis = axis && axis[1] ? axis[1] : 'se';
  154. }
  155. });
  156. //If we want to auto hide the elements
  157. if (o.autoHide) {
  158. o._handles.hide();
  159. $(self.element).addClass("ui-resizable-autohide").hover(function() {
  160. $(this).removeClass("ui-resizable-autohide");
  161. o._handles.show();
  162. },
  163. function(){
  164. if (!o.resizing) {
  165. $(this).addClass("ui-resizable-autohide");
  166. o._handles.hide();
  167. }
  168. });
  169. }
  170. this.mouseInit();
  171. },
  172. plugins: {},
  173. ui: function() {
  174. return {
  175. originalElement: this.originalElement,
  176. element: this.element,
  177. helper: this.helper,
  178. position: this.position,
  179. size: this.size,
  180. options: this.options,
  181. originalSize: this.originalSize,
  182. originalPosition: this.originalPosition
  183. };
  184. },
  185. propagate: function(n,e) {
  186. $.ui.plugin.call(this, n, [e, this.ui()]);
  187. if (n != "resize") this.element.triggerHandler(["resize", n].join(""), [e, this.ui()], this.options[n]);
  188. },
  189. destroy: function() {
  190. var el = this.element, wrapped = el.children(".ui-resizable").get(0);
  191. this.mouseDestroy();
  192. var _destroy = function(exp) {
  193. $(exp).removeClass("ui-resizable ui-resizable-disabled")
  194. .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
  195. };
  196. _destroy(el);
  197. if (el.is('.ui-wrapper') && wrapped) {
  198. el.parent().append(
  199. $(wrapped).css({
  200. position: el.css('position'),
  201. width: el.outerWidth(),
  202. height: el.outerHeight(),
  203. top: el.css('top'),
  204. left: el.css('left')
  205. })
  206. ).end().remove();
  207. _destroy(wrapped);
  208. }
  209. },
  210. mouseStart: function(e) {
  211. if(this.options.disabled) return false;
  212. var handle = false;
  213. for(var i in this.options.handles) {
  214. if($(this.options.handles[i])[0] == e.target) handle = true;
  215. }
  216. if (!handle) return false;
  217. var o = this.options, iniPos = this.element.position(), el = this.element,
  218. num = function(v) { return parseInt(v, 10) || 0; }, ie6 = $.browser.msie && $.browser.version < 7;
  219. o.resizing = true;
  220. o.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
  221. // bugfix #1749
  222. if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
  223. // sOffset decides if document scrollOffset will be added to the top/left of the resizable element
  224. var sOffset = $.browser.msie && !o.containment && (/absolute/).test(el.css('position')) && !(/relative/).test(el.parent().css('position'));
  225. var dscrollt = sOffset ? o.documentScroll.top : 0, dscrolll = sOffset ? o.documentScroll.left : 0;
  226. el.css({ position: 'absolute', top: (iniPos.top + dscrollt), left: (iniPos.left + dscrolll) });
  227. }
  228. //Opera fixing relative position
  229. if ($.browser.opera && /relative/.test(el.css('position')))
  230. el.css({ position: 'relative', top: 'auto', left: 'auto' });
  231. this._renderProxy();
  232. var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
  233. if (o.containment) {
  234. curleft += $(o.containment).scrollLeft()||0;
  235. curtop += $(o.containment).scrollTop()||0;
  236. }
  237. //Store needed variables
  238. this.offset = this.helper.offset();
  239. this.position = { left: curleft, top: curtop };
  240. this.size = o.helper || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
  241. this.originalSize = o.helper || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
  242. this.originalPosition = { left: curleft, top: curtop };
  243. this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
  244. this.originalMousePosition = { left: e.pageX, top: e.pageY };
  245. //Aspect Ratio
  246. o.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.height / this.originalSize.width)||1);
  247. if (o.preserveCursor)
  248. $('body').css('cursor', this.axis + '-resize');
  249. this.propagate("start", e);
  250. return true;
  251. },
  252. mouseDrag: function(e) {
  253. //Increase performance, avoid regex
  254. var el = this.helper, o = this.options, props = {},
  255. self = this, smp = this.originalMousePosition, a = this.axis;
  256. var dx = (e.pageX-smp.left)||0, dy = (e.pageY-smp.top)||0;
  257. var trigger = this._change[a];
  258. if (!trigger) return false;
  259. // Calculate the attrs that will be change
  260. var data = trigger.apply(this, [e, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
  261. if (o._aspectRatio || e.shiftKey)
  262. data = this._updateRatio(data, e);
  263. data = this._respectSize(data, e);
  264. // plugins callbacks need to be called first
  265. this.propagate("resize", e);
  266. el.css({
  267. top: this.position.top + "px", left: this.position.left + "px",
  268. width: this.size.width + "px", height: this.size.height + "px"
  269. });
  270. if (!o.helper && o.proportionallyResize)
  271. this._proportionallyResize();
  272. this._updateCache(data);
  273. // calling the user callback at the end
  274. this.element.triggerHandler("resize", [e, this.ui()], this.options["resize"]);
  275. return false;
  276. },
  277. mouseStop: function(e) {
  278. this.options.resizing = false;
  279. var o = this.options, num = function(v) { return parseInt(v, 10) || 0; }, self = this;
  280. if(o.helper) {
  281. var pr = o.proportionallyResize, ista = pr && (/textarea/i).test(pr.get(0).nodeName),
  282. soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
  283. soffsetw = ista ? 0 : self.sizeDiff.width;
  284. var s = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
  285. left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
  286. top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
  287. if (!o.animate)
  288. this.element.css($.extend(s, { top: top, left: left }));
  289. if (o.helper && !o.animate) this._proportionallyResize();
  290. }
  291. if (o.preserveCursor)
  292. $('body').css('cursor', 'auto');
  293. this.propagate("stop", e);
  294. if (o.helper) this.helper.remove();
  295. return false;
  296. },
  297. _updateCache: function(data) {
  298. var o = this.options;
  299. this.offset = this.helper.offset();
  300. if (data.left) this.position.left = data.left;
  301. if (data.top) this.position.top = data.top;
  302. if (data.height) this.size.height = data.height;
  303. if (data.width) this.size.width = data.width;
  304. },
  305. _updateRatio: function(data, e) {
  306. var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
  307. if (data.height) data.width = (csize.height / o.aspectRatio);
  308. else if (data.width) data.height = (csize.width * o.aspectRatio);
  309. if (a == 'sw') {
  310. data.left = cpos.left + (csize.width - data.width);
  311. data.top = null;
  312. }
  313. if (a == 'nw') {
  314. data.top = cpos.top + (csize.height - data.height);
  315. data.left = cpos.left + (csize.width - data.width);
  316. }
  317. return data;
  318. },
  319. _respectSize: function(data, e) {
  320. var el = this.helper, o = this.options, pRatio = o._aspectRatio || e.shiftKey, a = this.axis,
  321. ismaxw = data.width && o.maxWidth && o.maxWidth < data.width, ismaxh = data.height && o.maxHeight && o.maxHeight < data.height,
  322. isminw = data.width && o.minWidth && o.minWidth > data.width, isminh = data.height && o.minHeight && o.minHeight > data.height;
  323. if (isminw) data.width = o.minWidth;
  324. if (isminh) data.height = o.minHeight;
  325. if (ismaxw) data.width = o.maxWidth;
  326. if (ismaxh) data.height = o.maxHeight;
  327. var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
  328. var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
  329. if (isminw && cw) data.left = dw - o.minWidth;
  330. if (ismaxw && cw) data.left = dw - o.maxWidth;
  331. if (isminh && ch) data.top = dh - o.minHeight;
  332. if (ismaxh && ch) data.top = dh - o.maxHeight;
  333. // fixing jump error on top/left - bug #2330
  334. var isNotwh = !data.width && !data.height;
  335. if (isNotwh && !data.left && data.top) data.top = null;
  336. else if (isNotwh && !data.top && data.left) data.left = null;
  337. return data;
  338. },
  339. _proportionallyResize: function() {
  340. var o = this.options;
  341. if (!o.proportionallyResize) return;
  342. var prel = o.proportionallyResize, el = this.helper || this.element;
  343. if (!o.borderDif) {
  344. var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
  345. p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
  346. o.borderDif = $.map(b, function(v, i) {
  347. var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
  348. return border + padding;
  349. });
  350. }
  351. prel.css({
  352. height: (el.height() - o.borderDif[0] - o.borderDif[2]) + "px",
  353. width: (el.width() - o.borderDif[1] - o.borderDif[3]) + "px"
  354. });
  355. },
  356. _renderProxy: function() {
  357. var el = this.element, o = this.options;
  358. this.elementOffset = el.offset();
  359. if(o.helper) {
  360. this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
  361. // fix ie6 offset
  362. var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
  363. pxyoffset = ( ie6 ? 2 : -1 );
  364. this.helper.addClass(o.helper).css({
  365. width: el.outerWidth() + pxyoffset,
  366. height: el.outerHeight() + pxyoffset,
  367. position: 'absolute',
  368. left: this.elementOffset.left - ie6offset +'px',
  369. top: this.elementOffset.top - ie6offset +'px',
  370. zIndex: ++o.zIndex
  371. });
  372. this.helper.appendTo("body");
  373. if (o.disableSelection)
  374. $.ui.disableSelection(this.helper.get(0));
  375. } else {
  376. this.helper = el;
  377. }
  378. },
  379. _change: {
  380. e: function(e, dx, dy) {
  381. return { width: this.originalSize.width + dx };
  382. },
  383. w: function(e, dx, dy) {
  384. var o = this.options, cs = this.originalSize, sp = this.originalPosition;
  385. return { left: sp.left + dx, width: cs.width - dx };
  386. },
  387. n: function(e, dx, dy) {
  388. var o = this.options, cs = this.originalSize, sp = this.originalPosition;
  389. return { top: sp.top + dy, height: cs.height - dy };
  390. },
  391. s: function(e, dx, dy) {
  392. return { height: this.originalSize.height + dy };
  393. },
  394. se: function(e, dx, dy) {
  395. return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [e, dx, dy]));
  396. },
  397. sw: function(e, dx, dy) {
  398. return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [e, dx, dy]));
  399. },
  400. ne: function(e, dx, dy) {
  401. return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [e, dx, dy]));
  402. },
  403. nw: function(e, dx, dy) {
  404. return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [e, dx, dy]));
  405. }
  406. }
  407. }));
  408. $.extend($.ui.resizable, {
  409. defaults: {
  410. cancel: ":input",
  411. distance: 1,
  412. delay: 0,
  413. preventDefault: true,
  414. transparent: false,
  415. minWidth: 10,
  416. minHeight: 10,
  417. aspectRatio: false,
  418. disableSelection: true,
  419. preserveCursor: true,
  420. autoHide: false,
  421. knobHandles: false
  422. }
  423. });
  424. /*
  425. * Resizable Extensions
  426. */
  427. $.ui.plugin.add("resizable", "containment", {
  428. start: function(e, ui) {
  429. var o = ui.options, self = $(this).data("resizable"), el = self.element;
  430. var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
  431. if (!ce) return;
  432. self.containerElement = $(ce);
  433. if (/document/.test(oc) || oc == document) {
  434. self.containerOffset = { left: 0, top: 0 };
  435. self.containerPosition = { left: 0, top: 0 };
  436. self.parentData = {
  437. element: $(document), left: 0, top: 0,
  438. width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
  439. };
  440. }
  441. // i'm a node, so compute top, left, right, bottom
  442. else{
  443. self.containerOffset = $(ce).offset();
  444. self.containerPosition = $(ce).position();
  445. self.containerSize = { height: $(ce).innerHeight(), width: $(ce).innerWidth() };
  446. var co = self.containerOffset, ch = self.containerSize.height, cw = self.containerSize.width,
  447. width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
  448. self.parentData = {
  449. element: ce, left: co.left, top: co.top, width: width, height: height
  450. };
  451. }
  452. },
  453. resize: function(e, ui) {
  454. var o = ui.options, self = $(this).data("resizable"),
  455. ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
  456. pRatio = o._aspectRatio || e.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
  457. if (ce[0] != document && /static/.test(ce.css('position')))
  458. cop = self.containerPosition;
  459. if (cp.left < (o.helper ? co.left : cop.left)) {
  460. self.size.width = self.size.width + (o.helper ? (self.position.left - co.left) : (self.position.left - cop.left));
  461. if (pRatio) self.size.height = self.size.width * o.aspectRatio;
  462. self.position.left = o.helper ? co.left : cop.left;
  463. }
  464. if (cp.top < (o.helper ? co.top : 0)) {
  465. self.size.height = self.size.height + (o.helper ? (self.position.top - co.top) : self.position.top);
  466. if (pRatio) self.size.width = self.size.height / o.aspectRatio;
  467. self.position.top = o.helper ? co.top : 0;
  468. }
  469. var woset = (o.helper ? self.offset.left - co.left : (self.position.left - cop.left)) + self.sizeDiff.width,
  470. hoset = (o.helper ? self.offset.top - co.top : self.position.top) + self.sizeDiff.height;
  471. if (woset + self.size.width >= self.parentData.width) {
  472. self.size.width = self.parentData.width - woset;
  473. if (pRatio) self.size.height = self.size.width * o.aspectRatio;
  474. }
  475. if (hoset + self.size.height >= self.parentData.height) {
  476. self.size.height = self.parentData.height - hoset;
  477. if (pRatio) self.size.width = self.size.height / o.aspectRatio;
  478. }
  479. },
  480. stop: function(e, ui){
  481. var o = ui.options, self = $(this).data("resizable"), cp = self.position,
  482. co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
  483. var helper = $(self.helper), ho = helper.offset(), w = helper.innerWidth(), h = helper.innerHeight();
  484. if (o.helper && !o.animate && /relative/.test(ce.css('position')))
  485. $(this).css({ left: (ho.left - co.left), top: (ho.top - co.top), width: w, height: h });
  486. if (o.helper && !o.animate && /static/.test(ce.css('position')))
  487. $(this).css({ left: cop.left + (ho.left - co.left), top: cop.top + (ho.top - co.top), width: w, height: h });
  488. }
  489. });
  490. $.ui.plugin.add("resizable", "grid", {
  491. resize: function(e, ui) {
  492. var o = ui.options, self = $(this).data("resizable"), cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || e.shiftKey;
  493. o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
  494. 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);
  495. if (/^(se|s|e)$/.test(a)) {
  496. self.size.width = os.width + ox;
  497. self.size.height = os.height + oy;
  498. }
  499. else if (/^(ne)$/.test(a)) {
  500. self.size.width = os.width + ox;
  501. self.size.height = os.height + oy;
  502. self.position.top = op.top - oy;
  503. }
  504. else if (/^(sw)$/.test(a)) {
  505. self.size.width = os.width + ox;
  506. self.size.height = os.height + oy;
  507. self.position.left = op.left - ox;
  508. }
  509. else {
  510. self.size.width = os.width + ox;
  511. self.size.height = os.height + oy;
  512. self.position.top = op.top - oy;
  513. self.position.left = op.left - ox;
  514. }
  515. }
  516. });
  517. $.ui.plugin.add("resizable", "animate", {
  518. stop: function(e, ui) {
  519. var o = ui.options, self = $(this).data("resizable");
  520. var pr = o.proportionallyResize, ista = pr && (/textarea/i).test(pr.get(0).nodeName),
  521. soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
  522. soffsetw = ista ? 0 : self.sizeDiff.width;
  523. var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
  524. left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
  525. top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
  526. self.element.animate(
  527. $.extend(style, top && left ? { top: top, left: left } : {}), {
  528. duration: o.animateDuration || "slow", easing: o.animateEasing || "swing",
  529. step: function() {
  530. var data = {
  531. width: parseInt(self.element.css('width'), 10),
  532. height: parseInt(self.element.css('height'), 10),
  533. top: parseInt(self.element.css('top'), 10),
  534. left: parseInt(self.element.css('left'), 10)
  535. };
  536. if (pr) pr.css({ width: data.width, height: data.height });
  537. // propagating resize, and updating values for each animation step
  538. self._updateCache(data);
  539. self.propagate("animate", e);
  540. }
  541. }
  542. );
  543. }
  544. });
  545. $.ui.plugin.add("resizable", "ghost", {
  546. start: function(e, ui) {
  547. var o = ui.options, self = $(this).data("resizable"), pr = o.proportionallyResize, cs = self.size;
  548. if (!pr) self.ghost = self.element.clone();
  549. else self.ghost = pr.clone();
  550. self.ghost.css(
  551. { opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }
  552. )
  553. .addClass('ui-resizable-ghost').addClass(typeof o.ghost == 'string' ? o.ghost : '');
  554. self.ghost.appendTo(self.helper);
  555. },
  556. resize: function(e, ui){
  557. var o = ui.options, self = $(this).data("resizable"), pr = o.proportionallyResize;
  558. if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
  559. },
  560. stop: function(e, ui){
  561. var o = ui.options, self = $(this).data("resizable"), pr = o.proportionallyResize;
  562. if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
  563. }
  564. });
  565. $.ui.plugin.add("resizable", "alsoResize", {
  566. start: function(e, ui) {
  567. var o = ui.options, self = $(this).data("resizable"),
  568. _store = function(exp) {
  569. $(exp).each(function() {
  570. $(this).data("resizable-alsoresize", {
  571. width: parseInt($(this).width(), 10), height: parseInt($(this).height(), 10),
  572. left: parseInt($(this).css('left'), 10), top: parseInt($(this).css('top'), 10)
  573. });
  574. });
  575. };
  576. if (typeof(o.alsoResize) == 'object') {
  577. if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
  578. else { $.each(o.alsoResize, function(exp, c) { _store(exp); }); }
  579. }else{
  580. _store(o.alsoResize);
  581. }
  582. },
  583. resize: function(e, ui){
  584. var o = ui.options, self = $(this).data("resizable"), os = self.originalSize, op = self.originalPosition;
  585. var delta = {
  586. height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
  587. top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
  588. },
  589. _alsoResize = function(exp, c) {
  590. $(exp).each(function() {
  591. var start = $(this).data("resizable-alsoresize"), style = {}, css = c && c.length ? c : ['width', 'height', 'top', 'left'];
  592. $.each(css || ['width', 'height', 'top', 'left'], function(i, prop) {
  593. var sum = (start[prop]||0) + (delta[prop]||0);
  594. if (sum && sum >= 0)
  595. style[prop] = sum || null;
  596. });
  597. $(this).css(style);
  598. });
  599. };
  600. if (typeof(o.alsoResize) == 'object') {
  601. $.each(o.alsoResize, function(exp, c) { _alsoResize(exp, c); });
  602. }else{
  603. _alsoResize(o.alsoResize);
  604. }
  605. },
  606. stop: function(e, ui){
  607. $(this).removeData("resizable-alsoresize-start");
  608. }
  609. });
  610. })(jQuery);