1 /**
  2  * @fileOverview constrain extension for kissy
  3  * @author yiminghe@gmail.com, qiaohua@taobao.com
  4  */
  5 KISSY.add("component/uibase/constrain", function (S, DOM, Node) {
  6 
  7     /**
  8      * @name Constrain
  9      * @class
 10      * Constrain extension class.
 11      * Constrain component to specified region
 12      * @memberOf Component.UIBase
 13      */
 14     function Constrain() {
 15 
 16     }
 17 
 18     Constrain.ATTRS =
 19     /**
 20      * @lends Component.UIBase.Constrain.prototype
 21      */
 22     {
 23         /**
 24          * Config constrain region.
 25          * True: viewport
 26          * Node: specified element.
 27          * false: no constrain region.
 28          * @type NodeList|Boolean
 29          */
 30         constrain:{
 31             //不限制
 32             //true:viewport限制
 33             //node:限制在节点范围
 34             value:false
 35         }
 36     };
 37 
 38     /**
 39      * 获取受限区域的宽高, 位置
 40      * @return {Object | undefined} {left: 0, top: 0, maxLeft: 100, maxTop: 100}
 41      */
 42     function _getConstrainRegion(constrain) {
 43         var ret = null;
 44         if (!constrain) {
 45             return ret;
 46         }
 47         var el = this.get("el");
 48         if (constrain !== true) {
 49             constrain = Node.one(constrain);
 50             ret = constrain.offset();
 51             S.mix(ret, {
 52                 maxLeft:ret.left + constrain.outerWidth() - el.outerWidth(),
 53                 maxTop:ret.top + constrain.outerHeight() - el.outerHeight()
 54             });
 55         }
 56         // 没有指定 constrain, 表示受限于可视区域
 57         else {
 58             ret = {
 59                 left:DOM.scrollLeft(),
 60                 top:DOM.scrollTop()
 61             };
 62             S.mix(ret, {
 63                 maxLeft:ret.left + DOM.viewportWidth() - el.outerWidth(),
 64                 maxTop:ret.top + DOM.viewportHeight() - el.outerHeight()
 65             });
 66         }
 67 
 68         return ret;
 69     }
 70 
 71     Constrain.prototype = {
 72 
 73         __renderUI:function () {
 74             var self = this,
 75                 attrs = self.getAttrs(),
 76                 xAttr = attrs["x"],
 77                 yAttr = attrs["y"],
 78                 oriXSetter = xAttr["setter"],
 79                 oriYSetter = yAttr["setter"];
 80             xAttr.setter = function (v) {
 81                 var r = oriXSetter && oriXSetter.call(self, v);
 82                 if (r === undefined) {
 83                     r = v;
 84                 }
 85                 if (!self.get("constrain")) {
 86                     return r;
 87                 }
 88                 var _ConstrainExtRegion = _getConstrainRegion.call(
 89                     self, self.get("constrain"));
 90                 return Math.min(Math.max(r,
 91                     _ConstrainExtRegion.left),
 92                     _ConstrainExtRegion.maxLeft);
 93             };
 94             yAttr.setter = function (v) {
 95                 var r = oriYSetter && oriYSetter.call(self, v);
 96                 if (r === undefined) {
 97                     r = v;
 98                 }
 99                 if (!self.get("constrain")) {
100                     return r;
101                 }
102                 var _ConstrainExtRegion = _getConstrainRegion.call(
103                     self, self.get("constrain"));
104                 return Math.min(Math.max(r,
105                     _ConstrainExtRegion.top),
106                     _ConstrainExtRegion.maxTop);
107             };
108             self.addAttr("x", xAttr);
109             self.addAttr("y", yAttr);
110         }
111     };
112 
113 
114     return Constrain;
115 
116 }, {
117     requires:["dom", "node"]
118 });