From ef68436ac04da078ffdcacd7e1f785473a303d45 Mon Sep 17 00:00:00 2001 From: Giulio Cesare Solaroli Date: Sun, 02 Oct 2011 23:56:18 +0000 Subject: First version of the newly restructured repository --- (limited to 'frontend/beta/js/YUI-extensions/widgets/Resizable.js') diff --git a/frontend/beta/js/YUI-extensions/widgets/Resizable.js b/frontend/beta/js/YUI-extensions/widgets/Resizable.js new file mode 100644 index 0000000..6944683 --- a/dev/null +++ b/frontend/beta/js/YUI-extensions/widgets/Resizable.js @@ -0,0 +1,586 @@ +/** + * @class YAHOO.ext.Resizable + * @extends YAHOO.ext.util.Observable + *

Applies drag handles to an element to make it resizable. The drag handles are inserted into the element + * and positioned absolute. Some elements, such as a textarea or image, don't support this. To overcome that, you can wrap + * the textarea in a div and set "resizeChild" to true (or the id of the textarea), or set wrap:true in your config and + * the element will be wrapped for you automatically.


+ * Here's a Resizable with every possible config option and it's default value: +

+var resizer = new YAHOO.ext.Resizable('element-id', {
+    resizeChild : false,
+    adjustments : [0, 0],
+    minWidth : 5,
+    minHeight : 5,
+    maxWidth : 10000,
+    maxHeight : 10000,
+    enabled : true,
+    wrap: false, // true to wrap the element
+    width: null, // initial size
+    height: null, // initial size
+    animate : false,
+    duration : .35,
+    dynamic : false,
+    handles : false,
+    multiDirectional : false,
+    disableTrackOver : false,
+    easing : YAHOO.util.Easing ? YAHOO.util.Easing.easeOutStrong : null,
+    widthIncrement : 0,
+    heightIncrement : 0,
+    pinned : false,
+    width : null,
+    height : null,
+    preserveRatio : false,
+    transparent: false,
+    minX: 0,
+    minY: 0,
+    draggable: false
+});
+resizer.on('resize', myHandler);
+
+*

+ * To hide a particular handle, set it's display to none in CSS, or through script:
+ * resizer.east.setDisplayed(false); + *

+ * @constructor + * Create a new resizable component + * @param {String/HTMLElement/YAHOO.ext.Element} el The id or element to resize + * @param {Object} config configuration options + */ +YAHOO.ext.Resizable = function(el, config){ + this.el = getEl(el); + + if(config && config.wrap){ + config.resizeChild = this.el; + this.el = this.el.wrap(typeof config.wrap == 'object' ? config.wrap : null); + this.el.id = this.el.dom.id = config.resizeChild.id + '-rzwrap'; + this.el.setStyle('overflow', 'hidden'); + this.el.setPositioning(config.resizeChild.getPositioning()); + config.resizeChild.clearPositioning(); + if(!config.width || !config.height){ + var csize = config.resizeChild.getSize(); + //csize.width -= config.adjustments[0]; + //csize.height -= config.adjustments[1]; + this.el.setSize(csize.width, csize.height); + } + if(config.pinned && !config.adjustments){ + config.adjustments = 'auto'; + } + } + + this.proxy = this.el.createProxy({tag: 'div', cls: 'yresizable-proxy', id: this.el.id + '-rzproxy'}) + this.proxy.unselectable(); + + // the overlay traps mouse events while dragging and fixes iframe issue + this.overlay = this.el.createProxy({tag: 'div', cls: 'yresizable-overlay', html: ' '}); + this.overlay.unselectable(); + this.overlay.enableDisplayMode('block'); + this.overlay.mon('mousemove', this.onMouseMove, this, true); + this.overlay.mon('mouseup', this.onMouseUp, this, true); + + YAHOO.ext.util.Config.apply(this, config, { + /** True to resizeSize the first child or id/element to resize @type YAHOO.ext.Element */ + resizeChild : false, + /** String "auto" or an array [width, height] with values to be added to the resize operation's new size. @type Array/String */ + adjustments : [0, 0], + /** The minimum width for the element @type Number */ + minWidth : 5, + /** The minimum height for the element @type Number */ + minHeight : 5, + /** The maximum width for the element @type Number */ + maxWidth : 10000, + /** The maximum height for the element @type Number */ + maxHeight : 10000, + /** false to disable resizing @type Boolean */ + enabled : true, + /** True to animate the resize (not compatible with dynamic sizing) @type Boolean */ + animate : false, + /** Animation duration @type Float */ + duration : .35, + /** True to resize the element while dragging instead of using a proxy @type Boolean */ + dynamic : false, + // these 3 are only available at config time + /** String consisting of the resize handles to display. Valid handles are + * n (north), s (south) e (east), w (west), ne (northeast), nw (northwest), se (southeast), sw (southwest) + * and all (which applies them all). If this is blank it defaults to "e,s,se". Handles can be delimited using + * a space, comma or semi-colon. This is only applied at config time. @type String*/ + handles : false, + multiDirectional : false, + /** true to disable mouse tracking. This is only applied at config time. @type Boolean*/ + disableTrackOver : false, + /** Animation easing @type YAHOO.util.Easing */ + easing : YAHOO.util.Easing ? YAHOO.util.Easing.easeOutStrong : null, + /** The increment to snap the width resize in pixels (dynamic must be true) @type Number */ + widthIncrement : 0, + /** The increment to snap the height resize in pixels (dynamic must be true) @type Number */ + heightIncrement : 0, + /** true to pin the resize handles. This is only applied at config time. @type Boolean*/ + pinned : false, + /** The initial width for the element @type Number */ + width : null, + /** The initial height for the element @type Number */ + height : null, + /** true to preserve the initial size ratio. @type Boolean*/ + preserveRatio : false, + /** true for transparent handles. This is only applied at config time. @type Boolean*/ + transparent: false, + /** The minimum allowed page X for the element (only used for west resizing, defaults to 0) @type Number */ + minX: 0, + /** The minimum allowed page Y for the element (only used for north resizing, defaults to 0) @type Number */ + minY: 0, + /** convenience to initialize drag drop. @type Boolean*/ + draggable: false + }); + + if(this.pinned){ + this.disableTrackOver = true; + this.el.addClass('yresizable-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 = YAHOO.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 YAHOO.ext.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent); + } + } + // legacy + this.corner = this.southeast; + + this.activeHandle = null; + + if(this.resizeChild){ + if(typeof this.resizeChild == 'boolean'){ + this.resizeChild = YAHOO.ext.Element.get(this.el.dom.firstChild, true); + }else{ + this.resizeChild = YAHOO.ext.Element.get(this.resizeChild, true); + } + } + + if(this.adjustments == 'auto'){ + var rc = this.resizeChild; + var hw = this.west, he = this.east, hn = this.north, hs = this.south; + if(rc && (hw || hn)){ + rc.setRelativePositioned(); + rc.setLeft(hw ? hw.el.getWidth() : 0); + rc.setTop(hn ? hn.el.getHeight() : 0); + } + 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.resizeChild ? this.resizeChild.id : this.el.id); + } + + // public events + this.events = { + /** + * @event beforeresize + * Fired before resize is allowed. Set enabled to false to cancel resize. + * @param {YAHOO.ext.Resizable} this + * @param {YAHOO.ext.EventObject} e The mousedown event + */ + 'beforeresize' : new YAHOO.util.CustomEvent(), + /** + * @event resize + * Fired after a resize. + * @param {YAHOO.ext.Resizable} this + * @param {Number} width The new width + * @param {Number} height The new height + * @param {YAHOO.ext.EventObject} e The mouseup event + */ + 'resize' : new YAHOO.util.CustomEvent() + }; + + if(this.width !== null && this.height !== null){ + this.resizeTo(this.width, this.height); + }else{ + this.updateChildSize(); + } +}; + +YAHOO.extendX(YAHOO.ext.Resizable, YAHOO.ext.util.Observable, { + /** + * Perform a manual resize + * @param {Number} width + * @param {Number} height + */ + resizeTo : function(width, height){ + this.el.setSize(width, height); + this.updateChildSize(); + this.fireEvent('resize', this, width, height, null); + }, + + startSizing : function(e){ + this.fireEvent('beforeresize', this, e); + if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler + 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]]; + this.proxy.setBox(this.startBox); + + this.overlay.setSize(YAHOO.util.Dom.getDocumentWidth(), YAHOO.util.Dom.getDocumentHeight()); + this.overlay.show(); + + if(!this.dynamic){ + this.proxy.show(); + } + } + }, + + onMouseDown : function(handle, e){ + if(this.enabled){ + e.stopEvent(); + this.activeHandle = handle; + this.overlay.setStyle('cursor', handle.el.getStyle('cursor')); + this.startSizing(e); + } + }, + + onMouseUp : function(e){ + var size = this.resizeElement(); + this.resizing = false; + this.handleOut(); + this.overlay.hide(); + this.fireEvent('resize', this, size.width, size.height, e); + }, + + updateChildSize : function(){ + if(this.resizeChild){ + var el = this.el; + var child = this.resizeChild; + var adj = this.adjustments; + if(el.dom.offsetWidth){ + var b = el.getSize(true); + child.setSize(b.width+adj[0], b.height+adj[1]); + } + // Second call here for IE + // The first call enables instant resizing and + // the second call corrects scroll bars if they + // exist + if(YAHOO.ext.util.Browser.isIE){ + setTimeout(function(){ + if(el.dom.offsetWidth){ + var b = el.getSize(true); + child.setSize(b.width+adj[0], b.height+adj[1]); + } + }, 10); + } + } + }, + + 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); + }, + + resizeElement : function(){ + var box = this.proxy.getBox(); + //box.width = this.snap(box.width, this.widthIncrement); + //box.height = this.snap(box.height, this.heightIncrement); + //if(this.multiDirectional){ + 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); + //} + this.updateChildSize(); + this.proxy.hide(); + return box; + }, + + constrain : function(v, diff, m, mx){ + if(v - diff < m){ + diff = v - m; + }else if(v - diff > mx){ + diff = mx - v; + } + return diff; + }, + + onMouseMove : function(e){ + if(this.enabled){ + try{// try catch so if something goes wrong the user doesn't get hung + + //var curXY = this.startPoint; + var curSize = this.curSize || this.startBox; + var x = this.startBox.x, y = this.startBox.y; + var ox = x, oy = y; + var w = curSize.width, h = curSize.height; + var ow = w, oh = h; + var mw = this.minWidth, mh = this.minHeight; + var mxw = this.maxWidth, mxh = this.maxHeight; + var wi = this.widthIncrement; + var hi = this.heightIncrement; + + var eventXY = e.getXY(); + var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0])); + var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1])); + + var pos = this.activeHandle.position; + + 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': + var 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); + var tw = w; + w = ow * (h/oh); + x += tw - w; + break; + case 'west': + var th = h; + h = oh * (w/ow); + h = Math.min(Math.max(mh, h), mxh); + y += (th - h) / 2; + var tw = w; + w = ow * (h/oh); + x += tw - w; + break; + case 'northwest': + var tw = w; + var 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(e){} + } + }, + + handleOver : function(){ + if(this.enabled){ + this.el.addClass('yresizable-over'); + } + }, + + handleOut : function(){ + if(!this.resizing){ + this.el.removeClass('yresizable-over'); + } + }, + + /** + * Returns the element this component is bound to. + * @return {YAHOO.ext.Element} + */ + getEl : function(){ + return this.el; + }, + + /** + * Returns the resizeChild element (or null). + * @return {YAHOO.ext.Element} + */ + getResizeChild : function(){ + return this.resizeChild; + }, + + /** + * Destroys this resizable. If the element was wrapped and + * removeEl is not true then the wrap remains. + * @param {Boolean} removeEl (optional) true to remove the element from the DOM + */ + destroy : function(removeEl){ + this.proxy.remove(); + this.overlay.removeAllListeners(); + this.overlay.remove(); + var ps = YAHOO.ext.Resizable.positions; + for(var k in ps){ + if(typeof ps[k] != 'function' && this[ps[k]]){ + var h = this[ps[k]]; + h.el.removeAllListeners(); + h.el.remove(); + } + } + if(removeEl){ + this.el.update(''); + this.el.remove(); + } + } +}); + +// hash to map config positions to true positions +YAHOO.ext.Resizable.positions = { + n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast' +}; + + +YAHOO.ext.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){ + if(!this.tpl){ + // only initialize the template if resizable is used + var tpl = YAHOO.ext.DomHelper.createTemplate( + {tag: 'div', cls: 'yresizable-handle yresizable-handle-{0}', html: ' '} + ); + tpl.compile(); + YAHOO.ext.Resizable.Handle.prototype.tpl = tpl; + } + this.position = pos; + this.rz = rz; + this.el = this.tpl.append(rz.el.dom, [this.position], true); + this.el.unselectable(); + if(transparent){ + this.el.setOpacity(0); + } + this.el.mon('mousedown', this.onMouseDown, this, true); + if(!disableTrackOver){ + this.el.mon('mouseover', this.onMouseOver, this, true); + this.el.mon('mouseout', this.onMouseOut, this, true); + } +}; + +YAHOO.ext.Resizable.Handle.prototype = { + afterResize : function(rz){ + // do nothing + }, + + onMouseDown : function(e){ + this.rz.onMouseDown(this, e); + }, + + onMouseOver : function(e){ + this.rz.handleOver(this, e); + }, + + onMouseOut : function(e){ + this.rz.handleOut(this, e); + } +}; + + + -- cgit v0.9.0.2