1 /**
  2  * @fileOverview KISSY.Popup
  3  * @author qiaohua@taobao.com, yiminghe@gmail.com
  4  */
  5 KISSY.add('overlay/popup', function (S, Overlay, undefined) {
  6 
  7     /**
  8      * @class
  9      * KISSY Popup Component.
 10      * xclass: 'popup'.
 11      * @memberOf Overlay
 12      * @extends Overlay
 13      * @name Popup
 14      */
 15     var Popup = Overlay.extend(
 16         /**
 17          * @lends Overlay.Popup#
 18          */
 19         {
 20             /**
 21              * see {@link Component.UIBase.Box#show}
 22              * @name Overlay.Popup#show
 23              * @function
 24              */
 25 
 26 
 27 
 28             initializer:function () {
 29                 var self = this,
 30                 // 获取相关联的 DOM 节点
 31                     trigger = self.get("trigger");
 32                 if (trigger) {
 33                     if (self.get("triggerType") === 'mouse') {
 34                         self._bindTriggerMouse();
 35                         self.on('afterRenderUI', function () {
 36                             self._bindContainerMouse();
 37                         });
 38                     } else {
 39                         self._bindTriggerClick();
 40                     }
 41                 }
 42             },
 43 
 44             _bindTriggerMouse:function () {
 45                 var self = this,
 46                     trigger = self.get("trigger"),
 47                     timer;
 48 
 49                 self.__mouseEnterPopup = function (ev) {
 50                     self._clearHiddenTimer();
 51                     timer = S.later(function () {
 52                         self._showing(ev);
 53                         timer = undefined;
 54                     }, self.get('mouseDelay') * 1000);
 55                 };
 56 
 57                 S.each(trigger, function (el) {
 58                     S.one(el).on('mouseenter', self.__mouseEnterPopup);
 59                 });
 60 
 61                 self._mouseLeavePopup = function () {
 62                     if (timer) {
 63                         timer.cancel();
 64                         timer = undefined;
 65                     }
 66 
 67                     self._setHiddenTimer();
 68                 };
 69 
 70                 S.each(trigger, function (el) {
 71                     S.one(el).on('mouseleave', self._mouseLeavePopup);
 72                 });
 73             },
 74 
 75             _bindContainerMouse:function () {
 76                 var self = this;
 77                 self.get('el')
 78                     .on('mouseleave', self._setHiddenTimer, self)
 79                     .on('mouseenter', self._clearHiddenTimer, self);
 80             },
 81 
 82             _setHiddenTimer:function () {
 83                 var self = this;
 84                 self._hiddenTimer = S.later(function () {
 85                     self._hiding();
 86                 }, self.get('mouseDelay') * 1000);
 87             },
 88 
 89             _clearHiddenTimer:function () {
 90                 var self = this;
 91                 if (self._hiddenTimer) {
 92                     self._hiddenTimer.cancel();
 93                     self._hiddenTimer = undefined;
 94                 }
 95             },
 96 
 97             _bindTriggerClick:function () {
 98                 var self = this;
 99                 self.__clickPopup = function (ev) {
100                     ev.halt();
101                     if (self.get('toggle')) {
102                         self[self.get('visible') ? '_hiding' : '_showing'](ev);
103                     } else {
104                         self._showing(ev);
105                     }
106                 };
107                 S.each(self.get("trigger"), function (el) {
108                     S.one(el).on('click', self.__clickPopup);
109                 });
110             },
111 
112             _showing:function (ev) {
113                 var self = this;
114                 self.set('currentTrigger', S.one(ev.target));
115                 self.show();
116             },
117 
118             _hiding:function () {
119                 this.set('currentTrigger', undefined);
120                 this.hide();
121             },
122 
123             destructor:function () {
124                 var self = this,
125                     root,
126                     t = self.get("trigger");
127                 if (t) {
128                     if (self.__clickPopup) {
129                         t.each(function (el) {
130                             el.detach('click', self.__clickPopup);
131                         });
132                     }
133                     if (self.__mouseEnterPopup) {
134                         t.each(function (el) {
135                             el.detach('mouseenter', self.__mouseEnterPopup);
136                         });
137                     }
138 
139                     if (self._mouseLeavePopup) {
140                         t.each(function (el) {
141                             el.detach('mouseleave', self._mouseLeavePopup);
142                         });
143                     }
144                 }
145                 if (root = self.get('el')) {
146                     root.detach('mouseleave', self._setHiddenTimer, self)
147                         .detach('mouseenter', self._clearHiddenTimer, self);
148                 }
149             }
150         }, {
151             ATTRS:/**
152              * @lends Overlay.Popup#
153              */
154             {
155                 /**
156                  * Trigger elements to show popup.
157                  * @type NodeList
158                  */
159                 trigger:{                          // 触发器
160                     setter:function (v) {
161                         if (S.isString(v)) {
162                             v = S.all(v);
163                         }
164                         return v;
165                     }
166                 },
167                 /**
168                  * How to activate trigger element.
169                  * "click" or "mouse",Default:"click".
170                  * @type String
171                  */
172                 triggerType:{
173                     // 触发类型
174                     value:'click'
175                 },
176                 currentTrigger:{},
177                 /**
178                  * When trigger type is mouse, the delayed time to show popup.
179                  * Default:0.1, in seconds.
180                  * @type Number
181                  */
182                 mouseDelay:{
183                     // triggerType 为 mouse 时, Popup 显示的延迟时间, 默认为 100ms
184                     value:0.1
185                 },
186                 /**
187                  * When trigger type is click, whether support toggle. Default:false
188                  * @type Boolean
189                  */
190                 toggle:{
191                     // triggerType 为 click 时, Popup 是否有toggle功能
192                     value:false
193                 }
194             }
195         }, {
196             xclass:'popup',
197             priority:20
198         });
199 
200     return Popup;
201 }, {
202     requires:["./base"]
203 });
204 
205 /**
206  * 2011-05-17
207  *  - 承玉:利用 initializer , destructor ,ATTRS
208  **/