1 /**
  2  * @fileOverview Dynamic load waterfall items by monitor window scroll.
  3  * @author yiminghe@gmail.com
  4  */
  5 KISSY.add("waterfall/loader", function (S, Node, Waterfall) {
  6 
  7     var $ = Node.all,
  8         win = S.Env.host,
  9     // > timeChunk interval to allow adjust first
 10         SCROLL_TIMER = 50;
 11 
 12     /**
 13      * @name Loader
 14      * @extends Waterfall
 15      * @class
 16      * Dynamic load waterfall items by monitor window scroll.
 17      * @memberOf Waterfall
 18      */
 19     function Loader() {
 20         Loader.superclass.constructor.apply(this, arguments);
 21     }
 22 
 23     function doScroll() {
 24         var self = this;
 25         S.log("waterfall:doScroll");
 26         if (self.__loading) {
 27             return;
 28         }
 29         // 如果正在调整中,等会再看
 30         // 调整中的高度不确定,现在不适合判断是否到了加载新数据的条件
 31         if (self.isAdjusting()) {
 32             // 恰好 __onScroll 是 buffered . :)
 33             self.__onScroll();
 34             return;
 35         }
 36         var container = self.get("container"),
 37             colHeight = container.offset().top,
 38             diff = self.get("diff"),
 39             curColHeights = self.get("curColHeights");
 40         // 找到最小列高度
 41         if (curColHeights.length) {
 42             colHeight += Math.min.apply(Math, curColHeights);
 43         }
 44         // 动态载
 45         // 最小高度(或被用户看到了)低于预加载线
 46         if (diff + $(win).scrollTop() + $(win).height() > colHeight) {
 47             S.log("waterfall:loading");
 48             loadData.call(self);
 49         }
 50     }
 51 
 52     function loadData() {
 53         var self = this,
 54             container = self.get("container");
 55 
 56         self.__loading = 1;
 57 
 58         var load = self.get("load");
 59 
 60         load && load(success, end);
 61 
 62         function success(items, callback) {
 63             self.__loading = 0;
 64             self.addItems(items, callback);
 65         }
 66 
 67         function end() {
 68             self.end();
 69         }
 70     }
 71 
 72     Loader.ATTRS =
 73     /**
 74      * @lends Waterfall.Loader#
 75      */
 76     {
 77         /**
 78          * Preload distance below viewport.
 79          * Default: 0.
 80          * @type Number
 81          */
 82         diff:{
 83             value:0
 84         }
 85     };
 86 
 87 
 88     S.extend(Loader, Waterfall,
 89         /**
 90          * @lends Waterfall.Loader#
 91          */
 92         {
 93             _init:function () {
 94                 var self = this;
 95                 Loader.superclass._init.apply(self, arguments);
 96                 self.__onScroll = S.buffer(doScroll, SCROLL_TIMER, self);
 97                 // 初始化时立即检测一次,但是要等初始化 adjust 完成后.
 98                 self.__onScroll();
 99                 self.start();
100             },
101 
102             /**
103              * Start monitor scroll on window.
104              * @since 1.3
105              */
106             start:function () {
107                 var self = this;
108                 if (!self.__started) {
109                     $(win).on("scroll", self.__onScroll);
110                     self.__started = 1;
111                 }
112             },
113 
114             /**
115              * Stop monitor scroll on window.
116              */
117             end:function () {
118                 $(win).detach("scroll", this.__onScroll);
119             },
120 
121             /**
122              * Use end instead.
123              * @deprecated 1.3
124              */
125             pause:function () {
126                 this.end();
127             },
128 
129             /**
130              * Use start instead.
131              * @deprecated 1.3
132              */
133             resume:function () {
134                 this.start();
135             },
136 
137             /**
138              * Destroy this instance.
139              */
140             destroy:function () {
141                 var self = this;
142                 Loader.superclass.destroy.apply(self, arguments);
143                 $(win).detach("scroll", self.__onScroll);
144                 self.__started = 0;
145             }
146         });
147 
148     return Loader;
149 
150 }, {
151     requires:['node', './base']
152 });