Bug #20946 ยป 11812.diff
t3lib/class.t3lib_tceforms.php (working copy) | ||
---|---|---|
$GLOBALS['SOBE']->doc->loadPrototype();
|
||
$GLOBALS['SOBE']->doc->loadExtJS();
|
||
$GLOBALS['SOBE']->doc->addStyleSheet('ext.resizable', $this->backPath . '../t3lib/js/extjs/ux/resize.css');
|
||
$this->loadJavascriptLib('../t3lib/jsfunc.evalfield.js');
|
||
$this->loadJavascriptLib('../t3lib/js/extjs/ux/ext.resizable.js');
|
||
// @TODO: Change to loadJavascriptLib(), but fix "TS = new typoScript()" issue first - see bug #9494
|
||
$jsFile[] = '<script type="text/javascript" src="'.$this->backPath.'jsfunc.tbe_editor.js"></script>';
|
||
t3lib/js/extjs/tceforms.js (working copy) | ||
---|---|---|
Ext.QuickTips.init();
|
||
this.convertDateFieldsToDatePicker();
|
||
this.convertTextareasResizable();
|
||
},
|
||
convertDateFieldsToDatePicker: function() {
|
||
... | ... | |
menu.show(datepicker);
|
||
});
|
||
});
|
||
},
|
||
|
||
convertTextareasResizable: function() {
|
||
var textAreas = Ext.select("*[id^=tceforms-textarea-]");
|
||
textAreas.each(function(element) {
|
||
var dwrapped = new Ext.Resizable(element.dom.id, {
|
||
minWidth:200,
|
||
minHeight: 50,
|
||
dynamic: true
|
||
});
|
||
});
|
||
}
|
||
}
|
||
Ext.onReady(TYPO3.TCEFORMS.init, TYPO3.TCEFORMS);
|
t3lib/js/extjs/ux/ext.resizable.js (revision 0) | ||
---|---|---|
/**
|
||
* @class Ext.ux.EventZone
|
||
* <p>This class implements a "virtual element" at a relative size and position
|
||
* <i>within</i> an existing element. It provides mouse events from a zone of an element of
|
||
* defined dimensions.</p>
|
||
* <p>The zone is defined using <code>top</code>, <code>right</code>, <code>bottom</code>,
|
||
* <code>left</code>, <code>width</code> and <code>height</code> options which specify
|
||
* the bounds of the zone in a similar manner to the CSS style properties of those names.</p>
|
||
* @cfg {String|HtmlElement} el The element in which to create the zone.
|
||
* @cfg {Array} points An Array of points within the element defining the event zone.
|
||
* @cfg {Number} top The top of the zone. If negative means an offset from the bottom.
|
||
* @cfg {Number} right The right of the zone. If negative means an offset from the right.
|
||
* @cfg {Number} left The left of the zone. If negative means an offset from the right.
|
||
* @cfg {Number} bottom The bottom of the zone. If negative means an offset from the bottom.
|
||
* @cfg {Number} width The width of the zone.
|
||
* @cfg {Number} height The height of the zone.
|
||
* @constructor
|
||
* Create a new EventZone
|
||
* @param {Object} config The config object.
|
||
*/
|
||
Ext.ux.EventZone = Ext.extend(Ext.util.Observable, {
|
||
|
||
constructor: function(config) {
|
||
this.initialConfig = config;
|
||
this.addEvents(
|
||
/**
|
||
* @event mouseenter
|
||
* This event fires when the mouse enters the zone.
|
||
* @param {EventObject} e the underlying mouse event.
|
||
* @param {EventZone} this
|
||
*/
|
||
'mouseenter',
|
||
/**
|
||
* @event mousedown
|
||
* This event fires when the mouse button is depressed within the zone.
|
||
* @param {EventObject} e the underlying mouse event.
|
||
* @param {EventZone} this
|
||
*/
|
||
'mousedown',
|
||
/**
|
||
* @event mousemove
|
||
* This event fires when the mouse moves within the zone.
|
||
* @param {EventObject} e the underlying mouse event.
|
||
* @param {EventZone} this
|
||
*/
|
||
'mousemove',
|
||
/**
|
||
* @event mouseup
|
||
* This event fires when the mouse button is released within the zone.
|
||
* @param {EventObject} e the underlying mouse event.
|
||
* @param {EventZone} this
|
||
*/
|
||
'mouseup',
|
||
/**
|
||
* @event mouseenter
|
||
* This event fires when the mouse is clicked within the zone.
|
||
* @param {EventObject} e the underlying mouse event.
|
||
* @param {EventZone} this
|
||
*/
|
||
'click',
|
||
/**
|
||
* @event mouseleave
|
||
* This event fires when the mouse leaves the zone.
|
||
* @param {EventObject} e the underlying mouse event.
|
||
* @param {EventZone} this
|
||
*/
|
||
'mouseleave'
|
||
);
|
||
Ext.apply(this, config);
|
||
this.el = Ext.get(this.el);
|
||
|
||
// If a polygon within the element is specified...
|
||
if (this.points) {
|
||
this.polygon = new Ext.lib.Polygon(this.points);
|
||
this.points = this.polygon.points;
|
||
}
|
||
|
||
Ext.ux.EventZone.superclass.constructor.call(this);
|
||
this.el.on({
|
||
mouseenter: this.handleMouseEvent,
|
||
mousedown: this.handleMouseEvent,
|
||
mousemove: this.handleMouseEvent,
|
||
mouseup: this.handleMouseEvent,
|
||
click: this.handleMouseEvent,
|
||
mouseleave: this.handleMouseEvent,
|
||
scope: this
|
||
});
|
||
},
|
||
|
||
handleMouseEvent: function(e) {
|
||
var r = this.polygon ? this.getPolygon() : this.getRegion();
|
||
var inBounds = r.contains(e.getPoint());
|
||
|
||
switch (e.type) {
|
||
// mouseenter fires this
|
||
case 'mouseover':
|
||
if (inBounds) {
|
||
this.mouseIn = true;
|
||
this.fireEvent('mouseenter', e, this);
|
||
}
|
||
break;
|
||
// mouseleave fires this
|
||
case 'mouseout':
|
||
this.mouseIn = false;
|
||
this.fireEvent('mouseleave', e, this);
|
||
break;
|
||
case 'mousemove':
|
||
if (inBounds) {
|
||
if (this.mouseIn) {
|
||
this.fireEvent('mousemove', e, this);
|
||
} else {
|
||
this.mouseIn = true;
|
||
this.fireEvent('mouseenter', e, this);
|
||
}
|
||
} else {
|
||
if (this.mouseIn) {
|
||
this.mouseIn = false;
|
||
this.fireEvent('mouseleave', e, this);
|
||
}
|
||
}
|
||
break;
|
||
default:
|
||
if (inBounds) {
|
||
this.fireEvent(e.type, e, this);
|
||
}
|
||
}
|
||
},
|
||
|
||
getPolygon: function() {
|
||
var xy = this.el.getXY();
|
||
return this.polygon.translate(xy[0], xy[1]);
|
||
},
|
||
|
||
getRegion: function() {
|
||
var r = this.el.getRegion();
|
||
|
||
// Adjust left boundary of region
|
||
if (Ext.isNumber(this.left)) {
|
||
if (this.left < 0) {
|
||
r.left = r.right + this.left;
|
||
} else {
|
||
r.left += this.left;
|
||
}
|
||
}
|
||
|
||
// Adjust right boundary of region
|
||
if (Ext.isNumber(this.width)) {
|
||
r.right = r.left + this.width;
|
||
} else if (Ext.isNumber(this.right)) {
|
||
r.right = (this.right < 0) ? r.right + this.right : r.left + this.right;
|
||
}
|
||
|
||
// Adjust top boundary of region
|
||
if (Ext.isNumber(this.top)) {
|
||
if (this.top < 0) {
|
||
r.top = r.bottom + this.top;
|
||
} else {
|
||
r.top += this.top;
|
||
}
|
||
}
|
||
|
||
// Adjust bottom boundary of region
|
||
if (Ext.isNumber(this.height)) {
|
||
r.bottom = r.top + this.height;
|
||
} else if (Ext.isNumber(this.bottom)) {
|
||
r.bottom = (this.bottom < 0) ? r.bottom + this.bottom : r.top + this.bottom;
|
||
}
|
||
|
||
return r;
|
||
}
|
||
});
|
||
|
||
/**
|
||
* @class Ext.lib.Polygon
|
||
* <p>This class encapsulates an absolute area of the document bounded by a list of points.</p>
|
||
* @constructor
|
||
* Create a new Polygon
|
||
* @param {Object} points An Array of <code>[n,n]</code> point specification Arrays, or
|
||
* an Array of Ext.lib.Points, or an HtmlElement, or an Ext.lib.Region.
|
||
*/
|
||
Ext.lib.Polygon = Ext.extend(Ext.lib.Region, {
|
||
constructor: function(points) {
|
||
var i, l, el;
|
||
if (l = points.length) {
|
||
if (points[0].x) {
|
||
for (i = 0; i < l; i++) {
|
||
points[i] = [ points[i].x, points[i].y ];
|
||
}
|
||
}
|
||
this.points = points;
|
||
} else {
|
||
if (el = Ext.get(points)) {
|
||
points = Ext.lib.Region.getRegion(el.dom);
|
||
}
|
||
if (points instanceof Ext.lib.Region) {
|
||
this.points = [
|
||
[points.left, points.top],
|
||
[points.right, points.top],
|
||
[points.right, points.bottom],
|
||
[points.left, points.bottom]
|
||
];
|
||
}
|
||
}
|
||
},
|
||
|
||
/**
|
||
* Returns a new Polygon translated by the specified <code>X</code> and <code>Y</code> increments.
|
||
* @param xDelta {Number} The <code>X</code> translation increment.
|
||
* @param xDelta {Number} The <code>Y</code> translation increment.
|
||
* @return {Polygon} The resulting Polygon.
|
||
*/
|
||
translate: function(xDelta, yDelta) {
|
||
var r = [], p = this.points, l = p.length, i;
|
||
for (i = 0; i < l; i++) {
|
||
r[i] = [ p[i][0] + xDelta, p[i][1] + yDelta ];
|
||
}
|
||
return new Ext.lib.Polygon(r);
|
||
},
|
||
|
||
/**
|
||
* Returns the area of this Polygon.
|
||
*/
|
||
getArea: function() {
|
||
var p = this.points, l = p.length, area = 0, i, j = 0;
|
||
for (i = 0; i < l; i++) {
|
||
j++;
|
||
if (j == l) {
|
||
j = 0;
|
||
}
|
||
area += (p[i][0] + p[j][0]) * (p[i][1] - p[j][1]);
|
||
}
|
||
return area * 0.5;
|
||
},
|
||
|
||
/**
|
||
* Returns <code>true</code> if this Polygon contains the specified point. Thanks
|
||
* to http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html for the algorithm.
|
||
* @param pt {Point|Number} Either an Ext.lib.Point object, or the <code>X</code> coordinate to test.
|
||
* @param py {Number} <b>Optional.</b> If the first parameter was an <code>X</code> coordinate, this is the <code>Y</code> coordinate.
|
||
*/
|
||
contains: function(pt, py) {
|
||
var f = (arguments.length == 1),
|
||
testX = f ? pt.x : pt,
|
||
testY = f ? pt.y : py,
|
||
p = this.points,
|
||
nvert = p.length,
|
||
j = nvert - 1,
|
||
i, j, c = false;
|
||
for (i = 0; i < nvert; j = i++) {
|
||
if ( ((p[i][1] > testY) != (p[j][1] > testY)) &&
|
||
(testX < (p[j][0]-p[i][0]) * (testY-p[i][1]) / (p[j][1]-p[i][1]) + p[i][0])) {
|
||
c = !c;
|
||
}
|
||
}
|
||
return c;
|
||
}
|
||
});
|
||
|
||
/**
|
||
* @class Ext.Resizable
|
||
* @extends Ext.util.Observable
|
||
* <p>Applies virtual drag handles to an element to make it resizable.</p>
|
||
* <p>Here is the list of valid resize handles:</p>
|
||
* <pre>
|
||
Value Description
|
||
------ -------------------
|
||
'n' north
|
||
's' south
|
||
'e' east
|
||
'w' west
|
||
'nw' northwest
|
||
'sw' southwest
|
||
'se' southeast
|
||
'ne' northeast
|
||
'all' all
|
||
</pre>
|
||
* <p>Here's an example showing the creation of a typical Resizable:</p>
|
||
* <pre><code>
|
||
var resizer = new Ext.Resizable('element-id', {
|
||
handles: 'all',
|
||
minWidth: 200,
|
||
minHeight: 100,
|
||
maxWidth: 500,
|
||
maxHeight: 400,
|
||
pinned: true
|
||
});
|
||
resizer.on('resize', myHandler);
|
||
</code></pre>
|
||
* <p>To hide a particular handle, set its display to none in CSS, or through script:<br>
|
||
* resizer.east.setDisplayed(false);</p>
|
||
* @constructor
|
||
* Create a new resizable component
|
||
* @param {Mixed} el The id or element to resize
|
||
* @param {Object} config configuration options
|
||
*/
|
||
Ext.Resizable = function(el, config){
|
||
this.el = Ext.get(el);
|
||
|
||
/**
|
||
* The proxy Element that is resized in place of the real Element during the resize operation.
|
||
* This may be queried using {@link Ext.Element#getBox} to provide the new area to resize to.
|
||
* Read only.
|
||
* @type Ext.Element.
|
||
* @property proxy
|
||
*/
|
||
this.proxy = this.el.createProxy({tag: 'div', cls: 'x-resizable-proxy', id: this.el.id + '-rzproxy'}, Ext.getBody());
|
||
this.proxy.unselectable();
|
||
this.proxy.enableDisplayMode('block');
|
||
|
||
Ext.apply(this, config);
|
||
|
||
if(this.pinned){
|
||
this.disableTrackOver = true;
|
||
this.el.addClass('x-resizable-pinned');
|
||
}
|
||
// if the element isn't positioned, make it relative
|
||
var position = this.el.getStyle('position');
|
||
if(position != 'absolute' && position != 'fixed'){
|
||
this.el.setStyle('position', 'relative');
|
||
}
|
||
if(!this.handles){ // no handles passed, must be legacy style
|
||
this.handles = 's,e,se';
|
||
if(this.multiDirectional){
|
||
this.handles += ',n,w';
|
||
}
|
||
}
|
||
if(this.handles == 'all'){
|
||
this.handles = 'n s e w ne nw se sw';
|
||
}
|
||
var hs = this.handles.split(/\s*?[,;]\s*?| /);
|
||
var ps = Ext.Resizable.positions;
|
||
for(var i = 0, len = hs.length; i < len; i++){
|
||
if(hs[i] && ps[hs[i]]){
|
||
var pos = ps[hs[i]];
|
||
this[pos] = new Ext.Resizable.Handle(this, pos);
|
||
}
|
||
}
|
||
// legacy
|
||
this.corner = this.southeast;
|
||
|
||
if(this.handles.indexOf('n') != -1 || this.handles.indexOf('w') != -1){
|
||
this.updateBox = true;
|
||
}
|
||
this.activeHandle = null;
|
||
|
||
if(this.adjustments == 'auto'){
|
||
var hw = this.west, he = this.east, hn = this.north, hs = this.south;
|
||
this.adjustments = [
|
||
(he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
|
||
(hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
|
||
];
|
||
}
|
||
|
||
if(this.draggable){
|
||
this.dd = this.dynamic ?
|
||
this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
|
||
this.dd.setHandleElId(this.el.id);
|
||
}
|
||
|
||
this.addEvents(
|
||
/**
|
||
* @event beforeresize
|
||
* Fired before resize is allowed. Set {@link #enabled} to false to cancel resize.
|
||
* @param {Ext.Resizable} this
|
||
* @param {Ext.EventObject} e The mousedown event
|
||
*/
|
||
'beforeresize',
|
||
/**
|
||
* @event resize
|
||
* Fired after a resize.
|
||
* @param {Ext.Resizable} this
|
||
* @param {Number} width The new width
|
||
* @param {Number} height The new height
|
||
* @param {Ext.EventObject} e The mouseup event
|
||
*/
|
||
'resize'
|
||
);
|
||
|
||
if(this.width !== null && this.height !== null){
|
||
this.resizeTo(this.width, this.height);
|
||
}
|
||
if(Ext.isIE){
|
||
this.el.dom.style.zoom = 1;
|
||
}
|
||
Ext.Resizable.superclass.constructor.call(this);
|
||
};
|
||
|
||
Ext.extend(Ext.Resizable, Ext.util.Observable, {
|
||
|
||
/**
|
||
* @cfg {Array/String} adjustments String 'auto' or an array [width, height] with values to be <b>added</b> to the
|
||
* resize operation's new size (defaults to <tt>[0, 0]</tt>)
|
||
*/
|
||
adjustments : [0, 0],
|
||
/**
|
||
* @cfg {Boolean} animate True to animate the resize (not compatible with dynamic sizing, defaults to false)
|
||
*/
|
||
animate : false,
|
||
/**
|
||
* @cfg {Mixed} constrainTo Constrain the resize to a particular element
|
||
*/
|
||
/**
|
||
* @cfg {Boolean} draggable Convenience to initialize drag drop (defaults to false)
|
||
*/
|
||
draggable: false,
|
||
/**
|
||
* @cfg {Number} duration Animation duration if animate = true (defaults to 0.35)
|
||
*/
|
||
duration : 0.35,
|
||
/**
|
||
* @cfg {Boolean} dynamic True to resize the element while dragging instead of using a proxy (defaults to false)
|
||
*/
|
||
dynamic : false,
|
||
/**
|
||
* @cfg {String} easing Animation easing if animate = true (defaults to <tt>'easingOutStrong'</tt>)
|
||
*/
|
||
easing : 'easeOutStrong',
|
||
/**
|
||
* @cfg {Boolean} enabled False to disable resizing (defaults to true)
|
||
*/
|
||
enabled : true,
|
||
/**
|
||
* @property enabled Writable. False if resizing is disabled.
|
||
* @type Boolean
|
||
*/
|
||
/**
|
||
* @cfg {String} handles String consisting of the resize handles to display (defaults to undefined).
|
||
* Specify either <tt>'all'</tt> or any of <tt>'n s e w ne nw se sw'</tt>.
|
||
*/
|
||
handles : false,
|
||
/**
|
||
* @cfg {Boolean} multiDirectional <b>Deprecated</b>. Deprecated style of adding multi-direction resize handles.
|
||
*/
|
||
multiDirectional : false,
|
||
/**
|
||
* @cfg {Number} height The height of the element in pixels (defaults to null)
|
||
*/
|
||
height : null,
|
||
/**
|
||
* @cfg {Number} width The width of the element in pixels (defaults to null)
|
||
*/
|
||
width : null,
|
||
/**
|
||
* @cfg {Number} heightIncrement The increment to snap the height resize in pixels
|
||
* (only applies if <code>{@link #dynamic}==true</code>). Defaults to <tt>0</tt>.
|
||
*/
|
||
heightIncrement : 0,
|
||
/**
|
||
* @cfg {Number} widthIncrement The increment to snap the width resize in pixels
|
||
* (only applies if <code>{@link #dynamic}==true</code>). Defaults to <tt>0</tt>.
|
||
*/
|
||
widthIncrement : 0,
|
||
/**
|
||
* @cfg {Number} minHeight The minimum height for the element (defaults to 5)
|
||
*/
|
||
minHeight : 5,
|
||
/**
|
||
* @cfg {Number} minWidth The minimum width for the element (defaults to 5)
|
||
*/
|
||
minWidth : 5,
|
||
/**
|
||
* @cfg {Number} maxHeight The maximum height for the element (defaults to 10000)
|
||
*/
|
||
maxHeight : 10000,
|
||
/**
|
||
* @cfg {Number} maxWidth The maximum width for the element (defaults to 10000)
|
||
*/
|
||
maxWidth : 10000,
|
||
/**
|
||
* @cfg {Number} minX The minimum x for the element (defaults to 0)
|
||
*/
|
||
minX: 0,
|
||
/**
|
||
* @cfg {Number} minY The minimum x for the element (defaults to 0)
|
||
*/
|
||
minY: 0,
|
||
/**
|
||
* @cfg {Boolean} pinned True to ensure that the resize handles are always visible, false to display them only when the
|
||
* user mouses over the resizable borders. This is only applied at config time. (defaults to false)
|
||
*/
|
||
pinned : false,
|
||
/**
|
||
* @cfg {Boolean} preserveRatio True to preserve the original ratio between height
|
||
* and width during resize (defaults to false)
|
||
*/
|
||
preserveRatio : false,
|
||
/**
|
||
* @cfg {Ext.lib.Region} resizeRegion Constrain the resize to a particular region
|
||
*/
|
||
|
||
|
||
/**
|
||
* Perform a manual resize and fires the 'resize' event.
|
||
* @param {Number} width
|
||
* @param {Number} height
|
||
*/
|
||
resizeTo : function(width, height){
|
||
this.el.setSize(width, height);
|
||
this.fireEvent('resize', this, width, height, null);
|
||
},
|
||
|
||
// private
|
||
startSizing : function(e, handle){
|
||
this.fireEvent('beforeresize', this, e);
|
||
if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler
|
||
e.stopEvent();
|
||
|
||
Ext.getDoc().on({
|
||
scope: this,
|
||
mousemove: this.onMouseMove,
|
||
mouseup: {
|
||
fn: this.onMouseUp,
|
||
single: true,
|
||
scope: this
|
||
}
|
||
});
|
||
Ext.getBody().addClass('ux-resizable-handle-' + handle.position);
|
||
|
||
this.resizing = true;
|
||
this.startBox = this.el.getBox();
|
||
this.startPoint = e.getXY();
|
||
this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
|
||
(this.startBox.y + this.startBox.height) - this.startPoint[1]];
|
||
|
||
if(this.constrainTo) {
|
||
var ct = Ext.get(this.constrainTo);
|
||
this.resizeRegion = ct.getRegion().adjust(
|
||
ct.getFrameWidth('t'),
|
||
ct.getFrameWidth('l'),
|
||
-ct.getFrameWidth('b'),
|
||
-ct.getFrameWidth('r')
|
||
);
|
||
}
|
||
|
||
this.proxy.setStyle('visibility', 'hidden'); // workaround display none
|
||
this.proxy.show();
|
||
this.proxy.setBox(this.startBox);
|
||
if(!this.dynamic){
|
||
this.proxy.setStyle('visibility', 'visible');
|
||
}
|
||
}
|
||
},
|
||
|
||
// private
|
||
onMouseDown : function(handle, e){
|
||
if(this.enabled && !this.activeHandle){
|
||
e.stopEvent();
|
||
this.activeHandle = handle;
|
||
this.startSizing(e, handle);
|
||
}
|
||
},
|
||
|
||
// private
|
||
onMouseUp : function(e){
|
||
Ext.getBody().removeClass('ux-resizable-handle-' + this.activeHandle.position)
|
||
.un('mousemove', this.onMouseMove, this);
|
||
var size = this.resizeElement();
|
||
this.resizing = false;
|
||
this.handleOut(this.activeHandle);
|
||
this.proxy.hide();
|
||
this.fireEvent('resize', this, size.width, size.height, e);
|
||
this.activeHandle = null;
|
||
},
|
||
|
||
// private
|
||
snap : function(value, inc, min){
|
||
if(!inc || !value){
|
||
return value;
|
||
}
|
||
var newValue = value;
|
||
var m = value % inc;
|
||
if(m > 0){
|
||
if(m > (inc/2)){
|
||
newValue = value + (inc-m);
|
||
}else{
|
||
newValue = value - m;
|
||
}
|
||
}
|
||
return Math.max(min, newValue);
|
||
},
|
||
|
||
/**
|
||
* <p>Performs resizing of the associated Element. This method is called internally by this
|
||
* class, and should not be called by user code.</p>
|
||
* <p>If a Resizable is being used to resize an Element which encapsulates a more complex UI
|
||
* component such as a Panel, this method may be overridden by specifying an implementation
|
||
* as a config option to provide appropriate behaviour at the end of the resize operation on
|
||
* mouseup, for example resizing the Panel, and relaying the Panel's content.</p>
|
||
* <p>The new area to be resized to is available by examining the state of the {@link #proxy}
|
||
* Element. Example:
|
||
<pre><code>
|
||
new Ext.Panel({
|
||
title: 'Resize me',
|
||
x: 100,
|
||
y: 100,
|
||
renderTo: Ext.getBody(),
|
||
floating: true,
|
||
frame: true,
|
||
width: 400,
|
||
height: 200,
|
||
listeners: {
|
||
render: function(p) {
|
||
new Ext.Resizable(p.getEl(), {
|
||
handles: 'all',
|
||
pinned: true,
|
||
transparent: true,
|
||
resizeElement: function() {
|
||
var box = this.proxy.getBox();
|
||
p.updateBox(box);
|
||
if (p.layout) {
|
||
p.doLayout();
|
||
}
|
||
return box;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}).show();
|
||
</code></pre>
|
||
*/
|
||
resizeElement : function(){
|
||
var box = this.proxy.getBox();
|
||
if(this.updateBox){
|
||
this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
|
||
}else{
|
||
this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
|
||
}
|
||
if(!this.dynamic){
|
||
this.proxy.hide();
|
||
}
|
||
return box;
|
||
},
|
||
|
||
// private
|
||
constrain : function(v, diff, m, mx){
|
||
if(v - diff < m){
|
||
diff = v - m;
|
||
}else if(v - diff > mx){
|
||
diff = v - mx;
|
||
}
|
||
return diff;
|
||
},
|
||
|
||
// private
|
||
onMouseMove : function(e){
|
||
if(this.enabled && this.activeHandle){
|
||
try{// try catch so if something goes wrong the user doesn't get hung
|
||
|
||
if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
|
||
return;
|
||
}
|
||
|
||
//var curXY = this.startPoint;
|
||
var curSize = this.curSize || this.startBox,
|
||
x = this.startBox.x, y = this.startBox.y,
|
||
ox = x,
|
||
oy = y,
|
||
w = curSize.width,
|
||
h = curSize.height,
|
||
ow = w,
|
||
oh = h,
|
||
mw = this.minWidth,
|
||
mh = this.minHeight,
|
||
mxw = this.maxWidth,
|
||
mxh = this.maxHeight,
|
||
wi = this.widthIncrement,
|
||
hi = this.heightIncrement,
|
||
eventXY = e.getXY(),
|
||
diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])),
|
||
diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])),
|
||
pos = this.activeHandle.position,
|
||
tw,
|
||
th;
|
||
|
||
switch(pos){
|
||
case 'east':
|
||
w += diffX;
|
||
w = Math.min(Math.max(mw, w), mxw);
|
||
break;
|
||
case 'south':
|
||
h += diffY;
|
||
h = Math.min(Math.max(mh, h), mxh);
|
||
break;
|
||
case 'southeast':
|
||
w += diffX;
|
||
h += diffY;
|
||
w = Math.min(Math.max(mw, w), mxw);
|
||
h = Math.min(Math.max(mh, h), mxh);
|
||
break;
|
||
case 'north':
|
||
diffY = this.constrain(h, diffY, mh, mxh);
|
||
y += diffY;
|
||
h -= diffY;
|
||
break;
|
||
case 'west':
|
||
diffX = this.constrain(w, diffX, mw, mxw);
|
||
x += diffX;
|
||
w -= diffX;
|
||
break;
|
||
case 'northeast':
|
||
w += diffX;
|
||
w = Math.min(Math.max(mw, w), mxw);
|
||
diffY = this.constrain(h, diffY, mh, mxh);
|
||
y += diffY;
|
||
h -= diffY;
|
||
break;
|
||
case 'northwest':
|
||
diffX = this.constrain(w, diffX, mw, mxw);
|
||
diffY = this.constrain(h, diffY, mh, mxh);
|
||
y += diffY;
|
||
h -= diffY;
|
||
x += diffX;
|
||
w -= diffX;
|
||
break;
|
||
case 'southwest':
|
||
diffX = this.constrain(w, diffX, mw, mxw);
|
||
h += diffY;
|
||
h = Math.min(Math.max(mh, h), mxh);
|
||
x += diffX;
|
||
w -= diffX;
|
||
break;
|
||
}
|
||
|
||
var sw = this.snap(w, wi, mw);
|
||
var sh = this.snap(h, hi, mh);
|
||
if(sw != w || sh != h){
|
||
switch(pos){
|
||
case 'northeast':
|
||
y -= sh - h;
|
||
break;
|
||
case 'north':
|
||
y -= sh - h;
|
||
break;
|
||
case 'southwest':
|
||
x -= sw - w;
|
||
break;
|
||
case 'west':
|
||
x -= sw - w;
|
||
break;
|
||
case 'northwest':
|
||
x -= sw - w;
|
||
y -= sh - h;
|
||
break;
|
||
}
|
||
w = sw;
|
||
h = sh;
|
||
}
|
||
|
||
if(this.preserveRatio){
|
||
switch(pos){
|
||
case 'southeast':
|
||
case 'east':
|
||
h = oh * (w/ow);
|
||
h = Math.min(Math.max(mh, h), mxh);
|
||
w = ow * (h/oh);
|
||
break;
|
||
case 'south':
|
||
w = ow * (h/oh);
|
||
w = Math.min(Math.max(mw, w), mxw);
|
||
h = oh * (w/ow);
|
||
break;
|
||
case 'northeast':
|
||
w = ow * (h/oh);
|
||
w = Math.min(Math.max(mw, w), mxw);
|
||
h = oh * (w/ow);
|
||
break;
|
||
case 'north':
|
||
tw = w;
|
||
w = ow * (h/oh);
|
||
w = Math.min(Math.max(mw, w), mxw);
|
||
h = oh * (w/ow);
|
||
x += (tw - w) / 2;
|
||
break;
|
||
case 'southwest':
|
||
h = oh * (w/ow);
|
||
h = Math.min(Math.max(mh, h), mxh);
|
||
tw = w;
|
||
w = ow * (h/oh);
|
||
x += tw - w;
|
||
break;
|
||
case 'west':
|
||
th = h;
|
||
h = oh * (w/ow);
|
||
h = Math.min(Math.max(mh, h), mxh);
|
||
y += (th - h) / 2;
|
||
tw = w;
|
||
w = ow * (h/oh);
|
||
x += tw - w;
|
||
break;
|
||
case 'northwest':
|
||
tw = w;
|
||
th = h;
|
||
h = oh * (w/ow);
|
||
h = Math.min(Math.max(mh, h), mxh);
|
||
w = ow * (h/oh);
|
||
y += th - h;
|
||
x += tw - w;
|
||
break;
|
||
|
||
}
|
||
}
|
||
this.proxy.setBounds(x, y, w, h);
|
||
if(this.dynamic){
|
||
this.resizeElement();
|
||
}
|
||
}catch(ex){}
|
||
}
|
||
},
|
||
|
||
// private
|
||
handleOver : function(handle){
|
||
if(this.enabled){
|
||
Ext.getBody().addClass('ux-resizable-handle-' + handle.position);
|
||
}
|
||
},
|
||
|
||
// private
|
||
handleOut : function(handle){
|
||
if(!this.resizing){
|
||
Ext.getBody().removeClass('ux-resizable-handle-' + handle.position);
|
||
}
|
||
},
|
||
|
||
/**
|
||
* Returns the element this component is bound to.
|
||
* @return {Ext.Element}
|
||
*/
|
||
getEl : function(){
|
||
return this.el;
|
||
},
|
||
|
||
/**
|
||
* Destroys this resizable. If the element was wrapped and
|
||
* removeEl is not true then the element remains.
|
||
* @param {Boolean} removeEl (optional) true to remove the element from the DOM
|
||
*/
|
||
destroy : function(removeEl){
|
||
Ext.destroy(this.dd, this.proxy);
|
||
this.proxy = null;
|
||
|
||
var ps = Ext.Resizable.positions;
|
||
for(var k in ps){
|
||
if(typeof ps[k] != 'function' && this[ps[k]]){
|
||
this[ps[k]].destroy();
|
||
}
|
||
}
|
||
if(removeEl){
|
||
this.el.update('');
|
||
Ext.destroy(this.el);
|
||
this.el = null;
|
||
}
|
||
this.purgeListeners();
|
||
},
|
||
|
||
syncHandleHeight : function(){
|
||
var h = this.el.getHeight(true);
|
||
if(this.west){
|
||
this.west.el.setHeight(h);
|
||
}
|
||
if(this.east){
|
||
this.east.el.setHeight(h);
|
||
}
|
||
}
|
||
});
|
||
|
||
// private
|
||
// hash to map config positions to true positions
|
||
Ext.Resizable.positions = {
|
||
n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast'
|
||
};
|
||
Ext.Resizable.cfg = {
|
||
north: {left: 7, right: -7, height: 7},
|
||
south: {left: 7, right: -7, top: -7},
|
||
east: {top: 7, bottom: -7, left: -7},
|
||
west: {top: 7, bottom: -7, width: 7},
|
||
southeast: {top: -7, left: -7},
|
||
southwest: {top: -7, width: 7},
|
||
northwest: {height: 7, width: 7},
|
||
northeast: {left: -7, height: 7}
|
||
};
|
||
|
||
// private
|
||
Ext.Resizable.Handle = function(rz, pos){
|
||
this.position = pos;
|
||
this.rz = rz;
|
||
var cfg = Ext.Resizable.cfg[pos] || Ext.Resizable.cfg[Ext.Resizable.positions[pos]];
|
||
this.ez = new Ext.ux.EventZone(Ext.apply({
|
||
position: pos,
|
||
el: rz.el
|
||
}, cfg));
|
||
this.ez.on({
|
||
mousedown: this.onMouseDown,
|
||
mouseenter: this.onMouseOver,
|
||
mouseleave: this.onMouseOut,
|
||
scope: this
|
||
});
|
||
};
|
||
|
||
// private
|
||
Ext.Resizable.Handle.prototype = {
|
||
cursor: 'move',
|
||
|
||
// private
|
||
afterResize : function(rz){
|
||
// do nothing
|
||
},
|
||
// private
|
||
onMouseDown : function(e){
|
||
this.rz.onMouseDown(this, e);
|
||
},
|
||
// private
|
||
onMouseOver : function(e){
|
||
this.rz.handleOver(this, e);
|
||
},
|
||
// private
|
||
onMouseOut : function(e){
|
||
this.rz.handleOut(this, e);
|
||
},
|
||
// private
|
||
destroy : function(){
|
||
Ext.destroy(this.el);
|
||
this.el = null;
|
||
}
|
||
};
|
t3lib/js/extjs/ux/resize.css (revision 0) | ||
---|---|---|
.ux-resizable-handle-east, .ux-resizable-handle-east textarea {
|
||
cursor: e-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-south, .ux-resizable-handle-south textarea {
|
||
cursor: s-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-west, .ux-resizable-handle-west textarea {
|
||
cursor: w-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-north, .ux-resizable-handle-north textarea {
|
||
cursor: n-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-southeast, .ux-resizable-handle-southeast textarea {
|
||
cursor: se-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-northwest, .ux-resizable-handle-northwest textarea {
|
||
cursor: nw-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-northeast, .ux-resizable-handle-northeast textarea {
|
||
cursor: ne-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-southwest, .ux-resizable-handle-southwest textarea {
|
||
cursor: sw-resize;
|
||
}
|
||
.ux-resizable-handle-east, .ux-resizable-handle-east textarea {
|
||
cursor: e-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-south, .ux-resizable-handle-south textarea {
|
||
cursor: s-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-west, .ux-resizable-handle-west textarea {
|
||
cursor: w-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-north, .ux-resizable-handle-north textarea {
|
||
cursor: n-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-southeast, .ux-resizable-handle-southeast textarea {
|
||
cursor: se-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-northwest, .ux-resizable-handle-northwest textarea {
|
||
cursor: nw-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-northeast, .ux-resizable-handle-northeast textarea {
|
||
cursor: ne-resize;
|
||
}
|
||
|
||
.ux-resizable-handle-southwest, .ux-resizable-handle-southwest textarea {
|
||
cursor: sw-resize;
|
||
}
|