/** * @ignore * resizable support for kissy * @author yiminghe@gmail.com */ KISSY.add("resizable", function (S, Node, Base, DD, undefined) { var $ = Node.all, i, j, Draggable = DD.Draggable, CLS_PREFIX = "resizable-handler", horizontal = ["l", "r"], vertical = ["t", "b"], ATTRS_ORDER = ["width", "height", "top", "left"], hcNormal = { "t": function (minW, maxW, minH, maxH, ot, ol, ow, oh, diffT, diffL, preserveRatio) { var h = getBoundValue(minH, maxH, oh - diffT), t = ot + oh - h, w = 0; if (preserveRatio) { w = h / oh * ow; } return [w, h, t, 0] }, "b": function (minW, maxW, minH, maxH, ot, ol, ow, oh, diffT, diffL, preserveRatio) { var h = getBoundValue(minH, maxH, oh + diffT), w = 0; if (preserveRatio) { w = h / oh * ow; } return [w, h, 0, 0]; }, "r": function (minW, maxW, minH, maxH, ot, ol, ow, oh, diffT, diffL, preserveRatio) { var w = getBoundValue(minW, maxW, ow + diffL), h = 0; if (preserveRatio) { h = w / ow * oh; } return [w, h, 0, 0]; }, "l": function (minW, maxW, minH, maxH, ot, ol, ow, oh, diffT, diffL, preserveRatio) { var w = getBoundValue(minW, maxW, ow - diffL), h = 0, l = ol + ow - w; if (preserveRatio) { h = w / ow * oh; } return [w, h, 0, l] } }; for (i = 0; i < horizontal.length; i++) { for (j = 0; j < vertical.length; j++) { (function (h, v) { hcNormal[ h + v] = hcNormal[ v + h] = function () { return merge(hcNormal[h].apply(this, arguments), hcNormal[v].apply(this, arguments)); }; })(horizontal[i], vertical[j]); } } function merge(a1, a2) { var a = []; for (i = 0; i < a1.length; i++) { a[i] = a1[i] || a2[i]; } return a; } function getBoundValue(min, max, v) { return Math.min(Math.max(min, v), max); } function createDD(self) { var dds = self['dds'], node = self.get('node'), handlers = self.get('handlers'), preserveRatio, dragConfig = self.get('dragConfig'), prefixCls = self.get('prefixCls'), prefix = prefixCls + CLS_PREFIX; for (i = 0; i < handlers.length; i++) { var hc = handlers[i], el = $("<div class='" + prefix + " " + prefix + "-" + hc + "'></div>") .prependTo(node, undefined), dd = dds[hc] = new Draggable(S.mix({ node: el, cursor: null, groups: false }, dragConfig)); (function (hc, dd) { var startEdgePos; dd.on("drag", function (ev) { var dd = ev.target, ow = self._width, oh = self._height, minW = self.get("minWidth"), maxW = self.get("maxWidth"), minH = self.get("minHeight"), maxH = self.get("maxHeight"), diffT = ev.pageY - startEdgePos.top, diffL = ev.pageX - startEdgePos.left, ot = self._top, ol = self._left, region = {}, pos = hcNormal[hc](minW, maxW, minH, maxH, ot, ol, ow, oh, diffT, diffL, preserveRatio); for (i = 0; i < ATTRS_ORDER.length; i++) { if (pos[i]) { region[ATTRS_ORDER[i]] = pos[i]; } } self.fire('beforeResize', { handler: hc, dd: dd, region: region }); }); dd.on("dragstart", function () { startEdgePos = dd.get('startMousePos'); preserveRatio = self.get('preserveRatio'); self._width = node.width(); self._top = parseInt(node.css("top")); self._left = parseInt(node.css("left")); self._height = node.height(); self.fire('resizeStart', { handler: hc, dd: dd }); }); dd.on("dragend", function () { self.fire('resizeEnd', { handler: hc, dd: dd }); }); })(hc, dd); } } /** * Make a element resizable. * @class KISSY.Resizable * @extends KISSY.Base */ var Resizable = Base.extend({ initializer: function () { this['dds'] = {}; this.publish('beforeResize', { defaultFn: this._onBeforeResize }) }, _onBeforeResize: function (e) { this.get('node').css(e.region); this.fire('resize', { handler: e.hc, dd: e.dd, region: e.region }); }, _onSetNode: function () { createDD(this); }, _onSetDisabled: function (v) { var dds = this['dds']; S.each(dds, function (d) { d.set('disabled', v); }); }, destructor: function () { var self = this, d, dds = self['dds']; for (d in dds) { dds[d].destroy(); dds[d].get("node").remove(); delete dds[d]; } } }, { name: 'Resizable', ATTRS: { /** * KISSY Node to be resizable. * Need to be positioned 'relative' or 'absolute'. * @cfg {KISSY.NodeList} node */ /** * @ignore */ node: { setter: function (v) { return $(v); } }, /** * config for internal drag object * @cfg {Object} dragConfig */ /** * @ignore */ dragConfig: { }, /** * css prefix for handler elements. * @cfg {String} prefixCls */ /** * @ignore */ prefixCls: { value: 'ks-' }, /** * Whether disable current resizable. * @cfg {Boolean} disabled */ /** * disable or enable current resizable. * @property disabled * @type {Boolean} */ /** * @ignore */ disabled: {}, /** * Minimum width can current node resize to. * @cfg {Number} minWidth */ /** * Minimum width can current node resize to. * @property minWidth * @type {Number} */ /** * @ignore */ minWidth: { value: 0 }, /** * Minimum height can current node resize to. * @cfg {Number} minHeight */ /** * Minimum height can current node resize to. * @property minHeight * @type {Number} */ /** * @ignore */ minHeight: { value: 0 }, /** * Maximum width can current node resize to. * @cfg {Number} maxWidth */ /** * Maximum width can current node resize to, * it can be changed after initialization, * for example: responsive design. * @property maxWidth * @type {Number} */ /** * @ignore */ maxWidth: { value: Number['MAX_VALUE'] }, /** * Maximum height can current node resize to. * @cfg {Number} maxHeight */ /** * Maximum height can current node resize to. * @property maxHeight * @type {Number} */ /** * @ignore */ maxHeight: { value: Number['MAX_VALUE'] }, /** * Whether preserve width/height ratio when resizing * @cfg {Boolean} preserveRatio */ /** * @ignore */ preserveRatio: { value: false }, /** * directions can current node resize to. * @cfg {KISSY.Resizable.Handler} handlers */ /** * @ignore */ handlers: { // t,tr,r,br,b,bl,l,tl value: [] } } }); /** * Resizable handlers type. * @enum {String} KISSY.Resizable.Handler */ Resizable.Handler = { /** * bottom */ B: 'b', /** * top */ T: 't', /** * left */ L: 'l', /** * right */ R: 'r', /** * bottom-left */ BL: 'bl', /** * top-left */ TL: 'tl', /** * bottom-right */ BR: 'br', /** * top-right */ TR: 'tr' }; return Resizable; }, { requires: ["node", 'base', "dd"] });