为了更好的为您提供服务, 云效 邀请您使用持续交付相关功能。云效结合ECS、EDAS等服务为您提供完备的发布、部署、测试全研发流程,大大提升您的研发效率. 了解更多>

提交 24d59200f2a7f1cb236d4200d3c8cb2f3d8ab8ac

作者 lifesinger
1 个父辈 1f3bc3ff

imglazyload update to datalazyload

1 1  
2   -component.name=imglazyload
3   -component.files=imglazyload.js,spaceball.gif
4 2 \ No newline at end of file
  3 +component.name=datalazyload
  4 +component.files=datalazyload.js,dot.gif
5 5 \ No newline at end of file
... ...
1 1 <?xml version="1.0" encoding="utf-8"?>
2   -<project name="imglazyload.build" default="build" basedir=".">
  2 +<project name="datalazyload.build" default="build" basedir=".">
3 3 <description>Component Build File</description>
4 4  
5 5 <import file="../build.xml"/>
... ...
1 1 /**
2   - * 图片延迟加载组件
3   - * @module imglazyload
  2 + * 数据延迟加载组件
  3 + * 包括 img, textarea, 以及回调函数
  4 + * @module datalazyload
4 5 * @creator 玉伯<lifesinger@gmail.com>
5 6 * @depends kissy-core, yahoo-dom-event
6 7 */
7   -KISSY.add("imglazyload", function(S) {
  8 +KISSY.add("datalazyload", function(S) {
8 9  
9 10 var Y = YAHOO.util, Dom = Y.Dom, Event = Y.Event, Lang = YAHOO.lang,
10 11 win = window, doc = document,
11 12 DATA_SRC = "data-lazyload-src",
  13 + LAZY_TEXTAREA_CLS = "ks-datalazyload",
12 14 MOD = { AUTO: "auto", MANUAL: "manual" },
13 15 DEFAULT = "default",
14 16  
... ... @@ -16,30 +18,31 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
16 18  
17 19 /**
18 20 * 懒处理模式
19   - * auto - 自动化。html 输出时,不对 img.src 做任何处理
20   - * manual - 输出 html 时,已经将需要延迟加载的图片的 src 属性替换为 DATA_SRC
  21 + * auto - 自动化。html 输出时,不对 img.src 做任何处理
  22 + * manual - 输出 html 时,已经将需要延迟加载的图片的 src 属性替换为 DATA_SRC
  23 + * 注:对于 textarea 数据,只有手动模式
21 24 */
22 25 mod: MOD.AUTO,
23 26  
24 27 /**
25   - * 当前视窗往下,diff px 外的图片延迟加载
26   - * 适当设置此值,可以让用户在拖动时感觉图片已经加载好
  28 + * 当前视窗往下,diff px 外的 img/textarea 延迟加载
  29 + * 适当设置此值,可以让用户在拖动时感觉数据已经加载好
27 30 * 默认为当前视窗高度(两屏以外的才延迟加载)
28 31 */
29 32 diff: DEFAULT,
30 33  
31 34 /**
32   - * 占位指示
  35 + * 图像的占位
33 36 */
34   - placeholder: "http://a.tbcdn.cn/kissy/1.0.0/build/imglazyload/spaceball.gif"
  37 + placeholder: "http://a.tbcdn.cn/kissy/1.0.2/build/datalazyload/dot.gif"
35 38 };
36 39  
37 40 /**
38   - * 图片延迟加载组件
39   - * @class ImageLazyload
  41 + * 延迟加载组件
  42 + * @class DataLazyload
40 43 * @constructor
41 44 */
42   - function ImageLazyload(containers, config) {
  45 + function DataLazyload(containers, config) {
43 46 // factory or constructor
44 47 if (!(this instanceof arguments.callee)) {
45 48 return new arguments.callee(containers, config);
... ... @@ -75,6 +78,18 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
75 78 //this.images
76 79  
77 80 /**
  81 + * 需要延迟处理的 textarea
  82 + * @type Array
  83 + */
  84 + //this.areaes
  85 +
  86 + /**
  87 + * 和延迟项绑定的回调函数
  88 + * @type object
  89 + */
  90 + this.callbacks = {els: [], fns: []};
  91 +
  92 + /**
78 93 * 开始延迟的 Y 坐标
79 94 * @type number
80 95 */
... ... @@ -83,7 +98,7 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
83 98 this._init();
84 99 }
85 100  
86   - S.mix(ImageLazyload.prototype, {
  101 + S.mix(DataLazyload.prototype, {
87 102  
88 103 /**
89 104 * 初始化
... ... @@ -91,9 +106,9 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
91 106 */
92 107 _init: function() {
93 108 this.threshold = this._getThreshold();
94   - this.images = this._filterImgs();
  109 + this._filterItems();
95 110  
96   - if (this.images.length > 0) {
  111 + if (this._getItemsLength()) {
97 112 this._initLoadEvent();
98 113 }
99 114 },
... ... @@ -111,6 +126,13 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
111 126 },
112 127  
113 128 /**
  129 + * 获取当前延迟项的数量
  130 + */
  131 + _getItemsLength: function() {
  132 + return this.images.length + this.areaes.length + this.callbacks.els.length;
  133 + },
  134 +
  135 + /**
114 136 * 初始化加载事件
115 137 * @protected
116 138 */
... ... @@ -121,42 +143,49 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
121 143 Event.on(win, "scroll", loader);
122 144 Event.on(win, "resize", function() {
123 145 self.threshold = self._getThreshold();
124   - loader(true);
  146 + loader();
125 147 });
126 148  
127   - // 手工模式时,第一屏也有可能有 data-src 项
128   - if (this.config.mod === MOD.MANUAL) {
129   - // 需要立即加载一次,以保证第一屏图片可见
  149 + // 需要立即加载一次,以保证第一屏的延迟项可见
  150 + if (self._getItemsLength()) {
130 151 Event.onDOMReady(function() {
131   - self._loadImgs(true);
  152 + loadItems();
132 153 });
133 154 }
134 155  
135 156 // 加载函数
136   - function loader(force) {
  157 + function loader() {
137 158 if (timer) return;
138 159 timer = setTimeout(function() {
139   - self._loadImgs(force);
140   - if (self.images.length === 0) {
141   - Event.removeListener(win, "scroll", loader);
142   - Event.removeListener(win, "resize", loader);
143   - }
  160 + loadItems();
144 161 timer = null;
145 162 }, 100); // 0.1s 内,用户感觉流畅
146 163 }
  164 +
  165 + // 加载延迟项
  166 + function loadItems() {
  167 + self._loadImgs();
  168 + self._loadAreaes();
  169 + self._fireCallbacks();
  170 +
  171 + if (self._getItemsLength() === 0) {
  172 + Event.removeListener(win, "scroll", loader);
  173 + Event.removeListener(win, "resize", loader);
  174 + }
  175 + }
147 176 },
148 177  
149 178 /**
150   - * 获取并初始化需要延迟下载的图片
  179 + * 获取并初始化需要延迟的 img 和 textarea
151 180 * @protected
152 181 */
153   - _filterImgs: function() {
  182 + _filterItems: function() {
154 183 var containers = this.containers,
155 184 threshold = this.threshold,
156 185 placeholder = this.config.placeholder,
157 186 isManualMod = this.config.mod === MOD.MANUAL,
158   - n, N, imgs, i, len, img, data_src,
159   - ret = [];
  187 + n, N, imgs, areaes, i, len, img, data_src,
  188 + lazyImgs = [], lazyAreaes = [];
160 189  
161 190 for (n = 0,N = containers.length; n < N; ++n) {
162 191 imgs = containers[n].getElementsByTagName("img");
... ... @@ -168,7 +197,7 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
168 197 if (isManualMod) { // 手工模式,只处理有 data-src 的图片
169 198 if (data_src) {
170 199 img.src = placeholder;
171   - ret.push(img);
  200 + lazyImgs.push(img);
172 201 }
173 202 } else { // 自动模式,只处理 threshold 外无 data-src 的图片
174 203 // 注意:已有 data-src 的项,可能已有其它实例处理过,重复处理
... ... @@ -176,24 +205,31 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
176 205 if (Dom.getY(img) > threshold && !data_src) {
177 206 img.setAttribute(DATA_SRC, img.src);
178 207 img.src = placeholder;
179   - ret.push(img);
  208 + lazyImgs.push(img);
180 209 }
181 210 }
182 211 }
  212 +
  213 + // 处理 textarea
  214 + areaes = containers[n].getElementsByTagName("textarea");
  215 + for( i = 0, len = areaes.length; i < len; ++i) {
  216 + if(Dom.hasClass(areaes[i], LAZY_TEXTAREA_CLS)) {
  217 + lazyAreaes.push(areaes[i]);
  218 + }
  219 + }
183 220 }
184 221  
185   - return ret;
  222 + this.images = lazyImgs;
  223 + this.areaes = lazyAreaes;
186 224 },
187 225  
188 226 /**
189 227 * 加载图片
190 228 * @protected
191 229 */
192   - _loadImgs: function(force) {
193   - var scrollTop = Dom.getDocumentScrollTop();
194   - if (!force && scrollTop <= this.config.diff) return;
195   -
  230 + _loadImgs: function() {
196 231 var imgs = this.images,
  232 + scrollTop = Dom.getDocumentScrollTop(),
197 233 threshold = this.threshold + scrollTop,
198 234 i, img, data_src, remain = [];
199 235  
... ... @@ -211,10 +247,71 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
211 247 }
212 248  
213 249 this.images = remain;
  250 + },
  251 +
  252 + /**
  253 + * 加载 textarea 数据
  254 + * @protected
  255 + */
  256 + _loadAreaes: function() {
  257 + var areaes = this.areaes,
  258 + scrollTop = Dom.getDocumentScrollTop(),
  259 + threshold = this.threshold + scrollTop,
  260 + i, area, parent, remain = [];
  261 +
  262 + for (i = 0; area = areaes[i++];) {
  263 + parent = area.parentNode;
  264 + // 注:area 可能处于 display: none 状态,Dom.getY(area) 获取不到 Y 值
  265 + // 因此这里采用 area.parentNode
  266 + if (Dom.getY(parent) <= threshold) {
  267 + // parent.removeChild(area); TODO: 需不需要?
  268 + parent.innerHTML = area.value;
  269 + } else {
  270 + remain.push(area);
  271 + }
  272 + }
  273 +
  274 + this.areaes = remain;
  275 + },
  276 +
  277 + /**
  278 + * 触发回调
  279 + * @protected
  280 + */
  281 + _fireCallbacks: function() {
  282 + var callbacks = this.callbacks,
  283 + els = callbacks.els, fns = callbacks.fns,
  284 + scrollTop = Dom.getDocumentScrollTop(),
  285 + threshold = this.threshold + scrollTop,
  286 + i, el, fn, remainEls = [], remainFns = [];
  287 +
  288 + for (i = 0; (el = els[i]) && (fn = fns[i++]);) {
  289 + if (Dom.getY(el) <= threshold) {
  290 + fn.call(el);
  291 + } else {
  292 + remainEls.push(el);
  293 + remainFns.push(fn);
  294 + }
  295 +
  296 + }
  297 +
  298 + callbacks.els = remainEls;
  299 + callbacks.fns = remainFns;
  300 + },
  301 +
  302 + /**
  303 + * 添加回调函数。当 el 即将出现在视图中时,触发 fn
  304 + */
  305 + addCallback: function(el, fn) {
  306 + el = Dom.get(el);
  307 + if(el && typeof fn === "function") {
  308 + this.callbacks.els.push(el);
  309 + this.callbacks.fns.push(fn);
  310 + }
214 311 }
215 312 });
216 313  
217   - S.ImageLazyload = ImageLazyload;
  314 + S.DataLazyload = DataLazyload;
218 315 });
219 316  
220 317 /**
... ... @@ -252,10 +349,26 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
252 349 * 1. 初始窗口很小,拉大窗口时,图片加载正常
253 350 * 2. 页面有滚动位置时,刷新页面,图片加载正常
254 351 * 3. 手动模式,第一屏有延迟图片时,加载正常
  352 + *
  353 + * 2009-12-17 补充:
  354 + * 1. textarea 延迟加载约定:页面中需要延迟的 dom 节点,放在
  355 + * <textarea class="ks-datalazysrc invisible">dom code</textarea>
  356 + * 里。可以添加 hidden 等 class, 但建议用 invisible, 并设定 height = "实际高度".
  357 + * 这样可以保证滚动时,diff 更真实有效。
  358 + * 注意:textarea 加载后,会替换掉父容器中的所有内容。
  359 + *
  360 + * 2. 延迟 callback 约定:dataLazyload.addCallback(el, fn) 表示当 el 即将出现时,触发 fn.
  361 + *
  362 + * 3. 所有操作都是最多触发一次,比如 callback. 来回拖动滚动条时,只有 el 第一次出现时会触发 fn 回调。
255 363 */
256 364  
257 365 /**
258 366 * TODOs:
259 367 * - [取消] 背景图片的延迟加载(对于 css 里的背景图片和 sprite 很难处理)
260 368 * - [取消] 加载时的 loading 图(对于未设定大小的图片,很难完美处理[参考资料 4])
  369 + */
  370 +
  371 +/**
  372 + * UPDATE LOG:
  373 + * - 2009-12-17 yubo 将 imglazyload 升级为 datalazyload, 支持 textarea 方式延迟和触发回调函数
261 374 */
262 375 \ No newline at end of file
... ...
... ... @@ -625,8 +625,9 @@
625 625 </div>
626 626  
627 627 </div>
  628 +<h2>Textarea 延迟加载测试</h2>
628 629 <div class="box">
629   -
  630 +<textarea class="ks-datalazyload" style="visibility:hidden; height: 400px">
630 631 <div class="DetailResultItem">
631 632  
632 633 <div class="DetailPic">
... ... @@ -635,7 +636,7 @@
635 636 </div>
636 637  
637 638 <div class="PicDesc">
638   - <h3 class="PicTitle">優人神鼓 U - Theatre Dance with Drum</h3>
  639 + <h3 class="PicTitle">我是 Textarea 里面的内容 - Theatre Dance with Drum</h3>
639 640  
640 641 <div class="PicByLine">
641 642 by <a href="/photos/matthewfch/">Matthew Fang</a> (<a title="Hide Matthew Fang in this search" href="?q=%E4%BA%BA&amp;eui=76195812%40N00">hide</a>)
... ... @@ -698,8 +699,9 @@
698 699  
699 700  
700 701 </div>
701   -
  702 +</textarea>
702 703 </div>
  704 +
703 705 <div class="box">
704 706  
705 707 <div class="DetailResultItem">
... ... @@ -3202,7 +3204,7 @@
3202 3204 </div>
3203 3205  
3204 3206 </div>
3205   -<div class="box">
  3207 +<div class="box" id="lazyCallbackTest">
3206 3208  
3207 3209 <div class="DetailResultItem">
3208 3210  
... ... @@ -3212,7 +3214,7 @@
3212 3214 </div>
3213 3215  
3214 3216 <div class="PicDesc">
3215   - <h3 class="PicTitle">Morning fog 人在畫中</h3>
  3217 + <h3 class="PicTitle">出现我的时候,会 alert("Morning fog 人在畫中")</h3>
3216 3218  
3217 3219 <div class="PicByLine">
3218 3220 by <a href="/photos/chanmelmel/">Melinda ^..^</a> (<a title="Hide Melinda ^..^ in this search" href="?q=%E4%BA%BA&amp;eui=8945641%40N02">hide</a>)
... ... @@ -4566,10 +4568,13 @@
4566 4568 </div>
4567 4569 </div>
4568 4570 <script type="text/javascript" src="../kissy/kissy.js"></script>
4569   -<script type="text/javascript" src="imglazyload.js"></script>
  4571 +<script type="text/javascript" src="datalazyload.js"></script>
4570 4572 <script type="text/javascript">
4571   - KISSY().use("imglazyload", function(S){
4572   - S.ImageLazyload();
  4573 + KISSY().use("datalazyload", function(S){
  4574 + var lazyLoad = new S.DataLazyload();
  4575 + lazyLoad.addCallback("lazyCallbackTest", function() {
  4576 + alert("Morning fog 人在畫中");
  4577 + });
4573 4578 });
4574 4579 </script>
4575 4580 </body>
... ...