1 /**
  2  * @fileOverview Config constrain region for drag and drop
  3  * @author yiminghe@gmail.com
  4  */
  5 KISSY.add("dd/constrain", function (S, Base, Node) {
  6 
  7     var $ = Node.all, WIN = S.Env.host;
  8 
  9     /**
 10      * @class Provide ability to constrain draggable to specified region
 11      * @memberOf DD
 12      */
 13     function Constrain() {
 14         Constrain.superclass.constructor.apply(this, arguments);
 15     }
 16 
 17     function onDragStart(e) {
 18         var self = this,
 19             drag = e.drag,
 20             l, t, lt,
 21             dragNode = drag.get("dragNode"),
 22             constrain = self.get("constrain");
 23         if (constrain) {
 24             if (constrain === true) {
 25                 var win = $(WIN);
 26                 self.__constrainRegion = {
 27                     left:l = win.scrollLeft(),
 28                     top:t = win.scrollTop(),
 29                     right:l + win.width(),
 30                     bottom:t + win.height()
 31                 };
 32             }
 33             if (constrain.nodeType || S.isString(constrain)) {
 34                 constrain = $(constrain);
 35             }
 36             if (constrain.getDOMNode) {
 37                 lt = constrain.offset();
 38                 self.__constrainRegion = {
 39                     left:lt.left,
 40                     top:lt.top,
 41                     right:lt.left + constrain.outerWidth(),
 42                     bottom:lt.top + constrain.outerHeight()
 43                 };
 44             } else if (S.isPlainObject(constrain)) {
 45                 self.__constrainRegion = constrain;
 46             }
 47             if (self.__constrainRegion) {
 48                 self.__constrainRegion.right -= dragNode.outerWidth();
 49                 self.__constrainRegion.bottom -= dragNode.outerHeight();
 50             }
 51         }
 52     }
 53 
 54     function onDragAlign(e) {
 55         var self = this,
 56             info = e.info,
 57             l = info.left,
 58             t = info.top,
 59             constrain = self.__constrainRegion;
 60         if (constrain) {
 61             info.left = Math.min(Math.max(constrain.left, l), constrain.right);
 62             info.top = Math.min(Math.max(constrain.top, t), constrain.bottom);
 63         }
 64     }
 65 
 66     function onDragEnd() {
 67         this.__constrainRegion = null;
 68     }
 69 
 70     S.extend(Constrain, Base,
 71         /**
 72          * @lends DD.Constrain#
 73          */
 74         {
 75             __constrainRegion:null,
 76 
 77             /**
 78              * start monitoring drag
 79              * @param {DD.Draggable} drag
 80              */
 81             attachDrag:function (drag) {
 82                 var self = this;
 83                 drag.on("dragstart", onDragStart, self)
 84                     .on("dragend", onDragEnd, self)
 85                     .on("dragalign", onDragAlign, self);
 86             },
 87 
 88 
 89             /**
 90              * stop monitoring drag
 91              * @param {DD.Draggable} drag
 92              */
 93             detachDrag:function (drag) {
 94                 var self = this;
 95                 drag.detach("dragstart", onDragStart, self)
 96                     .detach("dragend", onDragEnd, self)
 97                     .detach("dragalign", onDragAlign, self);
 98             }
 99         }, {
100             ATTRS:/**
101              * @lends DD.Constrain#
102              */
103             {
104                 /**
105                  * constrained container
106                  * @type {Boolean|HTMLElement|String}
107                  */
108                 constrain:{
109                     value:true
110                 }
111             }
112         });
113 
114     return Constrain;
115 }, {
116     requires:['base', 'node']
117 });