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

提交 24d59200f2a7f1cb236d4200d3c8cb2f3d8ab8ac

作者 lifesinger
1 个父辈 1f3bc3ff

imglazyload update to datalazyload

1 1
2 -component.name=imglazyload  
3 -component.files=imglazyload.js,spaceball.gif  
4 \ No newline at end of file 2 \ No newline at end of file
  3 +component.name=datalazyload
  4 +component.files=datalazyload.js,dot.gif
5 \ No newline at end of file 5 \ No newline at end of file
1 <?xml version="1.0" encoding="utf-8"?> 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 <description>Component Build File</description> 3 <description>Component Build File</description>
4 4
5 <import file="../build.xml"/> 5 <import file="../build.xml"/>
1 /** 1 /**
2 - * 图片延迟加载组件  
3 - * @module imglazyload 2 + * 数据延迟加载组件
  3 + * 包括 img, textarea, 以及回调函数
  4 + * @module datalazyload
4 * @creator 玉伯<lifesinger@gmail.com> 5 * @creator 玉伯<lifesinger@gmail.com>
5 * @depends kissy-core, yahoo-dom-event 6 * @depends kissy-core, yahoo-dom-event
6 */ 7 */
7 -KISSY.add("imglazyload", function(S) { 8 +KISSY.add("datalazyload", function(S) {
8 9
9 var Y = YAHOO.util, Dom = Y.Dom, Event = Y.Event, Lang = YAHOO.lang, 10 var Y = YAHOO.util, Dom = Y.Dom, Event = Y.Event, Lang = YAHOO.lang,
10 win = window, doc = document, 11 win = window, doc = document,
11 DATA_SRC = "data-lazyload-src", 12 DATA_SRC = "data-lazyload-src",
  13 + LAZY_TEXTAREA_CLS = "ks-datalazyload",
12 MOD = { AUTO: "auto", MANUAL: "manual" }, 14 MOD = { AUTO: "auto", MANUAL: "manual" },
13 DEFAULT = "default", 15 DEFAULT = "default",
14 16
@@ -16,30 +18,31 @@ KISSY.add(&quot;imglazyload&quot;, function(S) { @@ -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 mod: MOD.AUTO, 25 mod: MOD.AUTO,
23 26
24 /** 27 /**
25 - * 当前视窗往下,diff px 外的图片延迟加载  
26 - * 适当设置此值,可以让用户在拖动时感觉图片已经加载好 28 + * 当前视窗往下,diff px 外的 img/textarea 延迟加载
  29 + * 适当设置此值,可以让用户在拖动时感觉数据已经加载好
27 * 默认为当前视窗高度(两屏以外的才延迟加载) 30 * 默认为当前视窗高度(两屏以外的才延迟加载)
28 */ 31 */
29 diff: DEFAULT, 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 * @constructor 43 * @constructor
41 */ 44 */
42 - function ImageLazyload(containers, config) { 45 + function DataLazyload(containers, config) {
43 // factory or constructor 46 // factory or constructor
44 if (!(this instanceof arguments.callee)) { 47 if (!(this instanceof arguments.callee)) {
45 return new arguments.callee(containers, config); 48 return new arguments.callee(containers, config);
@@ -75,6 +78,18 @@ KISSY.add(&quot;imglazyload&quot;, function(S) { @@ -75,6 +78,18 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
75 //this.images 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 * 开始延迟的 Y 坐标 93 * 开始延迟的 Y 坐标
79 * @type number 94 * @type number
80 */ 95 */
@@ -83,7 +98,7 @@ KISSY.add(&quot;imglazyload&quot;, function(S) { @@ -83,7 +98,7 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
83 this._init(); 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,9 +106,9 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
91 */ 106 */
92 _init: function() { 107 _init: function() {
93 this.threshold = this._getThreshold(); 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 this._initLoadEvent(); 112 this._initLoadEvent();
98 } 113 }
99 }, 114 },
@@ -111,6 +126,13 @@ KISSY.add(&quot;imglazyload&quot;, function(S) { @@ -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 * @protected 137 * @protected
116 */ 138 */
@@ -121,42 +143,49 @@ KISSY.add(&quot;imglazyload&quot;, function(S) { @@ -121,42 +143,49 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
121 Event.on(win, "scroll", loader); 143 Event.on(win, "scroll", loader);
122 Event.on(win, "resize", function() { 144 Event.on(win, "resize", function() {
123 self.threshold = self._getThreshold(); 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 Event.onDOMReady(function() { 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 if (timer) return; 158 if (timer) return;
138 timer = setTimeout(function() { 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 timer = null; 161 timer = null;
145 }, 100); // 0.1s 内,用户感觉流畅 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 * @protected 180 * @protected
152 */ 181 */
153 - _filterImgs: function() { 182 + _filterItems: function() {
154 var containers = this.containers, 183 var containers = this.containers,
155 threshold = this.threshold, 184 threshold = this.threshold,
156 placeholder = this.config.placeholder, 185 placeholder = this.config.placeholder,
157 isManualMod = this.config.mod === MOD.MANUAL, 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 for (n = 0,N = containers.length; n < N; ++n) { 190 for (n = 0,N = containers.length; n < N; ++n) {
162 imgs = containers[n].getElementsByTagName("img"); 191 imgs = containers[n].getElementsByTagName("img");
@@ -168,7 +197,7 @@ KISSY.add(&quot;imglazyload&quot;, function(S) { @@ -168,7 +197,7 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
168 if (isManualMod) { // 手工模式,只处理有 data-src 的图片 197 if (isManualMod) { // 手工模式,只处理有 data-src 的图片
169 if (data_src) { 198 if (data_src) {
170 img.src = placeholder; 199 img.src = placeholder;
171 - ret.push(img); 200 + lazyImgs.push(img);
172 } 201 }
173 } else { // 自动模式,只处理 threshold 外无 data-src 的图片 202 } else { // 自动模式,只处理 threshold 外无 data-src 的图片
174 // 注意:已有 data-src 的项,可能已有其它实例处理过,重复处理 203 // 注意:已有 data-src 的项,可能已有其它实例处理过,重复处理
@@ -176,24 +205,31 @@ KISSY.add(&quot;imglazyload&quot;, function(S) { @@ -176,24 +205,31 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
176 if (Dom.getY(img) > threshold && !data_src) { 205 if (Dom.getY(img) > threshold && !data_src) {
177 img.setAttribute(DATA_SRC, img.src); 206 img.setAttribute(DATA_SRC, img.src);
178 img.src = placeholder; 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 * @protected 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 var imgs = this.images, 231 var imgs = this.images,
  232 + scrollTop = Dom.getDocumentScrollTop(),
197 threshold = this.threshold + scrollTop, 233 threshold = this.threshold + scrollTop,
198 i, img, data_src, remain = []; 234 i, img, data_src, remain = [];
199 235
@@ -211,10 +247,71 @@ KISSY.add(&quot;imglazyload&quot;, function(S) { @@ -211,10 +247,71 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
211 } 247 }
212 248
213 this.images = remain; 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,10 +349,26 @@ KISSY.add(&quot;imglazyload&quot;, function(S) {
252 * 1. 初始窗口很小,拉大窗口时,图片加载正常 349 * 1. 初始窗口很小,拉大窗口时,图片加载正常
253 * 2. 页面有滚动位置时,刷新页面,图片加载正常 350 * 2. 页面有滚动位置时,刷新页面,图片加载正常
254 * 3. 手动模式,第一屏有延迟图片时,加载正常 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 * TODOs: 366 * TODOs:
259 * - [取消] 背景图片的延迟加载(对于 css 里的背景图片和 sprite 很难处理) 367 * - [取消] 背景图片的延迟加载(对于 css 里的背景图片和 sprite 很难处理)
260 * - [取消] 加载时的 loading 图(对于未设定大小的图片,很难完美处理[参考资料 4]) 368 * - [取消] 加载时的 loading 图(对于未设定大小的图片,很难完美处理[参考资料 4])
  369 + */
  370 +
  371 +/**
  372 + * UPDATE LOG:
  373 + * - 2009-12-17 yubo 将 imglazyload 升级为 datalazyload, 支持 textarea 方式延迟和触发回调函数
261 */ 374 */
262 \ No newline at end of file 375 \ No newline at end of file
@@ -625,8 +625,9 @@ @@ -625,8 +625,9 @@
625 </div> 625 </div>
626 626
627 </div> 627 </div>
  628 +<h2>Textarea 延迟加载测试</h2>
628 <div class="box"> 629 <div class="box">
629 - 630 +<textarea class="ks-datalazyload" style="visibility:hidden; height: 400px">
630 <div class="DetailResultItem"> 631 <div class="DetailResultItem">
631 632
632 <div class="DetailPic"> 633 <div class="DetailPic">
@@ -635,7 +636,7 @@ @@ -635,7 +636,7 @@
635 </div> 636 </div>
636 637
637 <div class="PicDesc"> 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 <div class="PicByLine"> 641 <div class="PicByLine">
641 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>) 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,8 +699,9 @@
698 699
699 700
700 </div> 701 </div>
701 - 702 +</textarea>
702 </div> 703 </div>
  704 +
703 <div class="box"> 705 <div class="box">
704 706
705 <div class="DetailResultItem"> 707 <div class="DetailResultItem">
@@ -3202,7 +3204,7 @@ @@ -3202,7 +3204,7 @@
3202 </div> 3204 </div>
3203 3205
3204 </div> 3206 </div>
3205 -<div class="box"> 3207 +<div class="box" id="lazyCallbackTest">
3206 3208
3207 <div class="DetailResultItem"> 3209 <div class="DetailResultItem">
3208 3210
@@ -3212,7 +3214,7 @@ @@ -3212,7 +3214,7 @@
3212 </div> 3214 </div>
3213 3215
3214 <div class="PicDesc"> 3216 <div class="PicDesc">
3215 - <h3 class="PicTitle">Morning fog 人在畫中</h3> 3217 + <h3 class="PicTitle">出现我的时候,会 alert("Morning fog 人在畫中")</h3>
3216 3218
3217 <div class="PicByLine"> 3219 <div class="PicByLine">
3218 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>) 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,10 +4568,13 @@
4566 </div> 4568 </div>
4567 </div> 4569 </div>
4568 <script type="text/javascript" src="../kissy/kissy.js"></script> 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 <script type="text/javascript"> 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 </script> 4579 </script>
4575 </body> 4580 </body>