/* @说明:瀑布流 Woo (Waterfall O O) */ ;(function(window, undefined){ var location = window.location, $W = $(window), // window窗口的高度,在初始方法中获得 WH, // window窗口的宽度,只在resize 开启的情况下有用,用于判断resize前后宽度是否变化 WW, H = $.History, // 当前瀑布流在所有瀑布流中的序号 IDX = 0, // 是否用户有点击进行翻页 USERCLICK = false, // 是否有tab 切换的事件发生 TABSW = false, BARSCROLL = false, // 是否正在返回顶部,$gotop 按键点击后返回页顶时设置其值为 true SCROLLINGTOTOP = false, TIMERINTERVAL, TIMERSCROLL, // 总容器 $HOLDER, PAGINE = [], MASN = [], // $.Woo.WooTemp 对象 WOOTEMP; var Woo = function(conf){ Woo.init(conf); }; $.extend(Woo,{ dfConf : { // 每个请求对应的form 的id 前缀,和 arrform 标识数组结合。 "formprefix" : '#woo-form-', // 组件框架选择符,依次为 总节点、tab切换触发器、tab切换容器、内容、内容翻页器、内容(与woo-pcont为同一节点,区别是已经masn过) "frame" : ['#woo-holder','.woo-swa','.woo-swb','.woo-pcont','.woo-pager','.woo-masned'], // 向前、向后的翻页按钮(区别于底部数字翻页器) "gopre" : null, "gonext" : null, // 回到顶部按钮 "gotop" : null, // 页面的尾部,所有在瀑布流翻页器之下的均可视为footer "footer" : null, // 单元节点dom选择器 "unit" : '.woo', // anchor 锚点名,回顶部会定位到该锚点处 "anchor" : 'woo-anchor', // 相对于 name="woo-anchor" 锚记的垂直方向偏移,可解决顶部fixed nav遮盖问题 "anchordiff" : 70, // 带 * 号的为特殊配置项 // 同一页面不同瀑布流可通过在.woo-pcont节点上设置 data- 的形式覆盖全局配置 // * 要插入到瀑布流左侧第一个位置或右侧第一个位置的节点 "sink" : $(null), // * 左(右)边第一列占位区块高度。sinkheight 如果为正值才有效 "sinkheight" : 0, // * 是否在右侧 sink 嵌入外部区块,否则是在左侧嵌入,前提是 sinkheight 为正值 "sinkright" : false, // * 每页的单元数 "unitsnum" : 24, // * 每一大页子页数量 "subpagenum" : 4, // scroll lock状态持续时间 "scrollwait" : 100, // 距离底部多远提前开始加载 "lbias" : 400, // 每次append插入dom的单元个数 "appendnum" : 12, // (逐个添加)是否逐个添加单元节点 "batchopen" : false, // (逐个添加) 每次插入节点的时间延迟,batchopen 开启后有效 "batchdelay" : 6, // (逐个添加) 每次插入dom的节点数,batchopen 开启后有效 "batchnum" : 2, // 当前页码前后显示的页码数 "nearbypagenum" : 3, // ajax 请求返回数据的默认类型 "ajaxdatatype" : "text", // ajax 请求是否缓存 "ajaxcache" : false, // resize 为 false 则 window resize 时不重绘,否则会调用默认的 resize 方法 "resize" : false, // whether refresh or keep the latest pagenum when switch waterfall "refreshwhenswitch" : false, // scroll 过程中执行的方法 "onScroll" : function (tp){ // tp 为当前的scrolltop }, // When preset html units are arranged ok "onFirstArrange" : function (idx){ // idx is the index of current waterfall }, // 每一大页加载完毕之后执行 "onOnePageOver" : function (pg, idx){ // pg 为 Pagine 实例,pg.$pager 为底部翻页容器 // idx 表示当前瀑布流的序号 // 可以使用 pg.hasNextUpperPage() pg.isLastSub() }, // 每次lazyAdd 结束之后执行 "onLazyAddOver" : function (pg, idx){ // pg 为 Pagine 实例,pg.$pager 为底部翻页容器 // idx 表示当前瀑布流的序号 }, // 每次 tabswitch 执行 "onTabSwitch" : function ($swtrigs,$swconts,a,pre,c){ // $swtrigs tabswitch 触发按钮 // $swconts tabswitch 内容区块 // a 表示当前序号 pre 表示前一个序号 c 表示是点击或自动播放触发的tabswitch }, // 每次请求后都要执行的方法 "requestAlways" : function (pg, idx){ // pg 为 Pagine 实例,pg.$pager 为底部翻页容器 // idx 表示当前瀑布流的序号 } }, /* @说明:switch切换配合瀑布流内容展示 @参数: conf - (Dic) 配置参数,将覆盖 dfconf ---- 以下为隐藏参数 dfconf 里没有他们的默认值 arrform - (Arr) 特征值组成的数组, 用途一:根据url上的hash 值判断当前聚焦项 用途二:和woo-form- 前缀组成form表单id arrsplit - (Arr) 请求分页地址的后半截,前半截在form表单里 arrmasnw - (Arr) 瀑布流每一列的扩展宽度,包含列间隔 arrmargin - (Arr) 瀑布流列之间的间隔 arrfmasnw - (Arr) 第一列特殊宽度 默认等于arrmasnw */ init : function (conf){ // 简化传参 if( typeof conf.arrsplit === 'string' ){ var tmpsplit = conf.arrsplit; conf.arrsplit = []; } if( typeof conf.arrmasnw === 'number' ){ var tmpmasnw = conf.arrmasnw; conf.arrmasnw = []; } if( typeof conf.arrmessw === 'number' ){ var tmpmessw = conf.arrmessw; conf.arrmessw = []; } if( typeof conf.arrmargin === 'number' ){ var tmpmargin = conf.arrmargin; conf.arrmargin = []; } if( typeof conf.arrfmasnw === 'number' ){ var tmpfmasnw = conf.arrfmasnw; conf.arrfmasnw = []; } if( typeof conf.arrgap === 'number' ){ var tmpgap = conf.arrgap; conf.arrgap = []; } for( var i=0; i 1 ){ Woo.$gopre.css("display","block") }else{ Woo.$gopre.css("display","none") } }); this.setClickGoPre(), this.setClickGoNext(), this.setClickGoTop(); // 处理 window scroll 事件 $W.scroll(function (){ BARSCROLL = true window.clearTimeout(TIMERSCROLL) TIMERSCROLL = window.setTimeout(function (){ BARSCROLL = false },Woo.conf.scrollwait) var tp = $W.scrollTop() Woo.$gotop.css('visibility',tp > 100 ? 'visible' : 'hidden') }) // 处理 window resize 事件,重新计算window 高度 $W.bind('resize',function (e){ Woo.throttle(function (){ WH = $W.height(); // 是否执行 resize 方法由 conf.resize 决定 if( conf.resize && WW != (WW=$W.width()) ){ Woo.resize(); } }, 100); }) }, iswebkit : null, // 相关dom 节点 $holder : $(null), // masn子类实例数组 masn : [], // pagine子类实例数组 pagine : [], /* @说明:整列重新调整 @参数: v - (Num) 增加的高度 sc - (Num) 参考单元所在屏数 co - (Num) 参考单元所在列数 tp - (Num) 参考单元的top值 */ resetCol : function(v,sc,co,tp){ var $masn = $HOLDER.find(this.conf.frame[5]+':visible').not('.woo-tmpmasn'), dacol = $masn.data('colY'); if( dacol && dacol[co] ){ dacol[co] += v; var mx = Math.max.apply(Math,dacol); // 重新设置高度,将新的 colY 保存到data 数据中 $masn.data('colY',dacol).css({"height":mx}) $HOLDER.find('div.co'+co).each(function (i,e){ var ttp = parseInt(e.style.top); if( ttp > tp ){ e.style.top = (ttp + v) + 'px'; } }) } }, /* @说明:节流控制函数,应用与窗口resize */ throttle : function(method, delay){ window.clearTimeout(Woo.throttle.timer); Woo.throttle.timer = setTimeout(function(){ method.call(this); },delay); }, /* @说明:窗口resize 时重绘 */ resize : function (){ // 重置所有MASN 的dom width for( var i=0; i 1 ? '-p'+upg : '')); } // 设置当前cont 的默认高度 $c.eq(a).find(Woo.conf.frame[3]).last().css('height',WH); } // 清除内存 WooTemp 对象,主要是MASNUNITS WOOTEMP && WOOTEMP.reset(); // 清除上一次瀑布流的缓存数据 if( PAGINE[pre] ){ PAGINE[pre].idata = [] PAGINE[pre].$data = $(null) } Woo._pageInit($conts,a,upg); },{"focus":"woo-cur","cont":frame[2],"index":Woo._getFocusIdx($trigs)}); }, /* @说明:内部方法,获取当前tab 的index 序号数 @参数: $conts - (Obj) 主内容节点 n - (Num) 每个切换所对应的序号数 gtoupg - (Num) 当前的大页码数 */ _pageInit : function($conts,n,gtoupg){ IDX = n; var conf = this.conf, frame = conf.frame, arrform = conf.arrform, arrsplit = conf.arrsplit, arrmasnw = conf.arrmasnw, arrmessw = conf.arrmessw, arrmargin = conf.arrmargin, arrfmasnw = conf.arrfmasnw, arrgap = conf.arrgap, splitstr = $.isArray(arrsplit) ? arrsplit[n] : '', $ccont = $conts.eq(n), $pg_cont = $ccont.find(frame[3]).not('.woo-tmpmasn'), $pg_pager = $ccont.find(frame[4]), // 各自.woo-pcont节点上设置 data-totalunits 总单元数 // 如不设置,翻页器将采用hasnext 模式 ucount = parseInt($pg_cont.data('totalunits')), pageunknown = isNaN(ucount), // np 代表瀑布流单元块形态,取值为数字 0,1,2... // 对应 masnunit.js 文件里的种种 np = $pg_cont.data('wootemp') || 0, // conf 里配置的 subpagenum 为全局配置 // 不同瀑布流可能有不同的配置需求,可在各自.woo-pcont节点上设置 data-subpagenum subpagenum = $pg_cont.data('subpagenum') || conf.subpagenum, // conf 里配置的 unitsnum 为全局配置 // 不同瀑布流可能有不同的配置需求,可在各自.woo-pcont节点上设置 data-unitsnum unitsnum = $pg_cont.data('unitsnum') || conf.unitsnum, sink = $pg_cont.data('sink') ? $($pg_cont.data('sink')) : $(conf.sink), sinkheight = $pg_cont.data('sinkheight') || conf.sinkheight, sinkright = !!$pg_cont.data('sinkright') || conf.sinkright, // 总子页码数 pcount = pageunknown ? 2 : Math.ceil(ucount/unitsnum), // 是否要扩展第一列,意思是与其它列的宽度不一样 isextended = !!arrfmasnw[n], // masn 每列宽度 wdt = arrmasnw[n], // mess width of this col mwdt = $.isArray(arrmessw) ? arrmessw[n] : null, wdt = mwdt ? wdt - mwdt : wdt, // 列与列之间的间隔 mgn = arrmargin[n], // 同一列间单元块之间的垂直间隔 gap = arrgap[n], // 是否支持扩展列,扩展列的宽度 fwdt = isextended ? wdt+arrfmasnw[n] : wdt, specialopen = fwdt != wdt, // 是否采用 nextMode 模式 hsn = pcount > 2 ? false : true, undefined; // 总共只有1个子页不隐藏 footer,否则隐藏之 this.$footer.css("display", pcount == 1 ? "block" : "none"); if( !PAGINE[n] ){ var pgcache, $pgdata = $(null); this.masn[n] = MASN[n] = new Woo.Masn($pg_cont,{ unit : conf.unit, gap : gap || 0, onAppend : Woo._doLoadImage, onFirstArrange : conf.onFirstArrange, onArrange : function ($c){ if( $c.length ){ pgcache = 2; $pgdata = $c; } if( PAGINE[n] ){ PAGINE[n].caching = 1; PAGINE[n].$data = $c; } // _onscroll 总控 if( TIMERINTERVAL ){ window.clearTimeout(TIMERINTERVAL) } Woo._onscroll() }, initAppendCounts : unitsnum, sinkWhat : sink, firstHeight : sinkheight, rightAlignFirstBlock : sinkright, specialColumnOpen : specialopen, firstColumnWidth : fwdt, columnMessWidth : mwdt, columnWidth : wdt, columnMargin : mgn, batchOpen : conf.batchopen, batchDelay : conf.batchdelay, batchNum : conf.batchnum }) this.pagine[n] = PAGINE[n] = new Woo.Pagine([$pg_cont,$pg_pager],{ identity : '!' + arrform[n], // 请求拆解后的数组,分解为3个元素 arrRequestUrl : [$(conf.formprefix+arrform[n])[0],splitstr], // 请求分页数据,请求结束后 always 执行 requestAlways : conf.requestAlways, onOnePageOver : conf.onOnePageOver, // ajax 请求返回数据类型 ajaxDataType : conf.ajaxdatatype, // ajax 请求是否缓存 ajaxCache : conf.ajaxcache, // 触发下翻页的scroll 偏离值,例如提前100px触发 scrollBias : conf.lbias, // 翻页按钮点击后的 锚点定位 anchor : conf.anchor, // 相对于 name="woo-anchor" 锚记的垂直方向偏移,可解决顶部fixed nav遮盖问题 anchorDiff : conf.anchordiff, // 当前页码前后显示的页码数 nearbyPageNum : conf.nearbypagenum, // 每一大页子页数量 subPageNum : subpagenum, // 每页的单元数 unitsPerSub : unitsnum, // 当前大页码数 currentUpperPage : gtoupg, // 总子页码数 totalPageNum : pcount, caching : pgcache, // masn 第一页装入的unit dom $data : $pgdata, // 是否采用 hasNext 模式 nextMode : hsn, analyzeResponse : WOOTEMP ? WOOTEMP.analyzeResponse[np] : $.noop, // 分解小块加载 lazyAdd : function (emp){ var pg = this, c = pg.config; // 如果没有数据直接返回 if( pg.$data.length === 0 && pg.idata.length === 0 ){ pg.caching = 0; // 如果到达最后,则显示footer if( pg.isLastSub() ){ pg.showFooter(); } return; } pg.lazyAdding = true, pg.caching = 1; var $da = pg.$data, ida = pg.idata, len1 = $da && $da.length || 0, len2 = ida && ida.length || 0, tlen = len1 + len2, // Math.max(MASN[n].spaceNum(),6), 计算合适的填充数 snum = emp ? Math.max(tlen + 1,c.unitsPerSub) : Woo.conf.appendnum, rnum = len1 + len2 - snum, addfirst = false; if( emp && MASN[n] ){ MASN[n].clearColY(), addfirst = true; } var $madd, imadd; if( snum <= len1 ){ // 全部使用$da 里的数据 $madd = $da.slice(0,snum), pg.$data = $da.slice(snum); }else{ $madd = $da, pg.$data = $(null), imadd = ida.slice(0,snum-len1), pg.idata = ida.slice(snum-len1); } // Start = new Date().getTime() // 这里生成的jonhtml 可能是 string 类型 // 也可能是 [] 数组 // 这两种情况均需要 $() 后再使用 var jonhtml = WOOTEMP && WOOTEMP.render[np] ? WOOTEMP.render[np](imadd) : imadd; MASN[n].appendContents($madd,jonhtml,false,false,addfirst,Woo.conf.batchnum,function (lastscreen,screen){ // End = new Date().getTime() if( rnum <= 0 ){ // pg 指代 Pagine 对象实例 pg.caching = 0; var cp = pg.currentPage, spn = c.subPageNum; // 预加载第二页 if( cp % spn === 0 && pg.currentPage != pg.totalPageNum ){ window.setTimeout(function (){ pg.prepareNext() },400) } // 如果到达最后,则显示footer if( pg.isLastSub() ){ pg.showFooter() } }else{ pg.caching = rnum <= c.unitsPerSub ? 1 : 2, // 设置翻页器不可见 pg.$pager.css({"height" : 0,"overflow" : "hidden"}); } window.setTimeout(function (){ pg.lazyAdding = false; Woo.conf.onLazyAddOver(pg, IDX); },200) }); } }); }else{ // 使用 USERCLICK // 为了避免在loading 过程中hash change 导致的无法准确回退 if( !PAGINE[n].lazyAdding && !PAGINE[n].loading || !USERCLICK ){ PAGINE[n].lazyAdding = true, PAGINE[n].scrollLoading = true; MASN[n].setCols(); // 第二次点击时重新取得数据,保证数据得到及时更新,默认刷新当前页 PAGINE[n].refreshPage(gtoupg); } } // 为了避免在loading 过程中hash change 导致的无法准确回退 USERCLICK = false, Woo.$gonext.css('visibility', 'hidden'); }, /* @说明:从hash值中获取当前页的标识字符串 */ _getIdentityFromHash : function (){ var u = ''; if( H ){ u = H.getHash(), u = u.split('-')[0]; } return u; }, /* @说明:从当前瀑布流的属性值中获取大页码数 */ _getPageNumFromHash : function (){ var n = 1; if( H ){ var hash = H.getHash(); hash = hash.split('-p')[1]; if( hash ){ n = parseInt(hash) || n; } } return n; }, /* @说明:内部方法,获取当前tab triger 的序号数 @参数: $trigs - (obj) 切换触发节点 */ _getFocusIdx : function($trigs){ var arrform = Woo.conf.arrform, hs = Woo._getIdentityFromHash().substr(1), fcn = -1; for( var i=0; i $('body').height() - Woo.conf.lbias ){ // pageinate 绑定的scroll事件 第二个参数不再作scroll 高度判断直接进入 PAGINE[IDX].doLazyAdd(tp,true), PAGINE[IDX].doLoadNext(); ////////// } // 如果滚动轴scrollbar 没有在滚动 if( !BARSCROLL ){ // 外部配置的onScroll 方法 Woo.conf.onScroll(tp) if( $HOLDER.length ){ var conf = Woo.conf, $gopre = Woo.$gopre, $gonext = Woo.$gonext, $pagerv = $HOLDER.find(conf.frame[4]+':visible'), cond1 = $pagerv.find('.woo-pbr').length, cond2 = PAGINE[IDX] && PAGINE[IDX].hasNextUpperPage; $gopre.add($gonext).css('visibility',tp > $HOLDER.position().top && ( !cond1 || cond1 && cond2 ) ? 'visible' : 'hidden') } } } window.clearTimeout(TIMERINTERVAL), TIMERINTERVAL = window.setTimeout(Woo._onscroll,100); }, /* @说明:内部方法,添加节点时的并行方法,加载单元内的图片 @参数: $u - (obj) 单元节点 */ _doLoadImage : function($u){ // 设置了 srcd 的情况下 $u.find('img[srcd]').each(function (i,e){ var $e = $(e), or = $e.attr('srcd'); //如果事先设置了 srcd 取代图片 src if( or ){ $e.css("display","none") .one('load',function (){ $(this).css({ "visibility" : "visible" }) .fadeIn(400) }) // 当图片加载失败,捕获error 重新加载 .one('error',function (){ var $t = $(this) $({}).delay(1000).queue(function (){ $t.one('error',function (){ $t.attr('src',or) }) .attr('src',or) }) }) .attr('src',or).removeAttr('srcd') } }) } }); /* @说明:Pagine 类 */ Woo.Pagine = function (id,opts){ this.init(id,opts); } Woo.Pagine.prototype = { /* @说明:pagine 类初始化方法 @参数: id - (Arr) 两部分容器。id[0]页面内容容器;id[1]翻页器 opts - (Dic) 配置参数,详见类实例化的相关代码 */ init : function (id,opts){ this.config = $.extend({}, opts); var pg=this, c = pg.config, upg = c.currentUpperPage, spn = c.subPageNum, undefined; pg.hasNextUpperPage = true, pg.caching = c.caching, pg.$data = c.$data || $(null), pg.idata = [], pg.$dom = id[0], pg.$pager = id[1], pg.unitsPerSub = c.unitsPerSub, pg.totalPageNum = c.totalPageNum, pg.currentUpperPage = upg, pg.currentPage = (upg-1)*spn + 1, // loading 状态条 pg.$loadingsm = $('
'); // 分析arrurl 即 c.arrRequestUrl 第一参数是form 才是正确的,否则不会发起请求 var arrurl = c.arrRequestUrl; if( $.type(arrurl[0]) === 'object' && arrurl[0].tagName.toLowerCase() === 'form' ){ pg.arrurl = arrurl; } // 如果分页内容为空,则自动发起请求 if( !pg.$dom.find(':first-child').length ){ // 此参数用于判断 是否清空cont 这里设为false 因为本来就是空 pg.clearCont = false, pg.loadPage(pg.currentPage, 1 ); }else if( upg > 1 ){ pg.clearCont = true, pg.loadPage(pg.currentPage, 1); }else{ pg.setPager(); } }, /* @说明:装载当前页内容,包括两部分,内容置于contObj节点内;翻页器置于pager节点内 @参数: cp - (Num) 当前页码数 sub - (Bool) 加载subpage 中 direct - (Bool) 和 .halting 配合解决中途翻页的问题 */ loadPage : function (cp,sub,direct){ if(this.loading){ this.scrollLoading = false; return; } var pg = this, c = pg.config, spn = c.subPageNum, isFirstSub = sub && ( cp % spn === 1 || spn == 1 ), clear = false, undefined; !sub && pg.scrollToAnchor(), pg.$pager.css("display","none"), pg.pagerVisible = false, pg.loading = true, // 分页页码重新计算,此段js 必须在 pg.currentPage = cp 之前 pg.currentUpperPage = cp; if(spn > 1 && !sub){ cp = (cp - 1) * spn + 1; }else if(spn > 1 && sub){ pg.currentUpperPage = Math.floor((cp-.1)/spn) + 1; } if( (!sub || isFirstSub) && pg.clearCont ){ //url hash定位 只在firstSub 时改变hash pg.changeHashOnFirstLoad(c.identity, pg.currentUpperPage); // 为了避免在loading 过程中hash change 导致的无法准确回退 USERCLICK = true, clear = true, pg.$dom.empty(); } pg.isPagerClick = false; pg._requestData(cp,sub,direct,false,clear); }, /* @说明:平滑scroll 到指定锚点处 */ scrollToAnchor : function (){ var pg = this, c = pg.config, $body = Woo.iswebkit ? $('body') : $('html'), $tohsh = $('a[name='+c.anchor+']'); // 分页内容容器置空,先置空内容再做 anchor 定位 if( c.anchor && $tohsh.length ){ // 此处由于导航设置fix 跟随,需要额外减去70 的高度 var at = $tohsh.offset().top - c.anchorDiff || 0; if( $body.scrollTop() > at ){ $body.animate({scrollTop:at},200); } }else{ // 除了ie6 其它浏览器不要设置默认回顶部,会造成切换时页面跳动 // 这里用到了 ActiveXObject 和 XMLHttpRequest 对象来区分 ie6 if( !!window.ActiveXObject && !window.XMLHttpRequest ){ $body.animate({scrollTop:0},200); } } }, /* @说明:获取当前的大页码数 */ getPageNum : function (){ return this.currentUpperPage; }, /* @说明:goto 到指定页码数 @参数: cp - (Num) 页码数 */ gotoPage : function (cp){ var pg = this; pg.clearCont = true, pg.loadPage(cp,false,true); }, /* @说明:刷新指定upper page,没传值则刷新当前页面 */ refreshPage : function (n){ var pg = this, upg = n || pg.currentUpperPage; pg.$data = $(null), pg.idata = [], pg.caching = 0, pg.halting = true, pg.loading = false, pg.gotoPage(upg); }, /* @说明:上下翻页,每次翻动一页,有方向性 @参数: dir - (Num) 当dir=1时,向下翻页页码数+1;当dir=-1时,向上翻页页码数-1 direct - (Bool) 和 .halting 配合解决中途翻页的问题 */ slidePage : function (dir,direct){ var pg = this, cp = pg.currentUpperPage; pg.clearCont = true, pg.loadPage(cp+dir,false,direct); }, /* @说明:对应子页翻页 @参数: dir - (Num) 当dir=1时,向下翻页页码数+1;当dir=-1时,向上翻页页码数-1 */ slideSubPage : function (dir){ var pg = this, cp = pg.currentPage; pg.clearCont = true, pg.loadPage(cp+dir,1); }, /* @说明:指定页码翻页,输入页码数 */ jumpPage : function (){ var pg = this, mypto = pg.$pager.find('[type=text]').val() || 0; if(mypto){ pg.clearCont = true, pg.loadPage(mypto); } }, /* @说明:预加载下一页的第一子页数据 */ prepareNext : function (){ var pg = this, cp = pg.currentPage; // 如果还没有prepare if( !pg.prepare || pg.prepare[0] !== cp+1 ){ pg._requestData(cp+1,true,false,true) } }, /* @说明:请求结束后马上执行,并处理请求到的 html 片段 参数: */ requestOver : function (cp,sub,jsndata,hasnext,totalunit){ var pg = this, c = pg.config, // 判断contObj 里的内容是否为空,即是否有过大翻页 emp = !pg.$dom.find(':first-child').length, spn = c.subPageNum, isFirstSub = cp % spn === 1, //第一子页 undefined; pg.hasNoMore = !hasnext, // currentPage 当前子页码数 pg.currentPage = cp, pg.caching = 2; /***************** 原 afterRequest 内容 ****************/ // totalunit 源自请求返回数据里的相应字段,建议每次请求都返回unit 总数 // 如果有 totalunit 更新 pg.totalPageNum if( totalunit ){ pg.totalPageNum = Math.ceil(totalunit/c.unitsPerSub) } // 如果是第一页 通过emp 判断 if( emp ){ //page loading 仍然在继续 pg.loading = true; } var thn = c.nextMode, tcp = pg.currentPage, tup = pg.currentUpperPage || tcp, ttp = pg.totalPageNum, $loadingsm = pg.$loadingsm, undefined; // 主内容区块消除正在加载的标识 pg.$dom.removeClass('woo-loading'); // 如果已经是最后一个子页 if( !pg.isLastSub() ){ $loadingsm.css('visibility','hidden'); } if( thn || tcp === ttp ){ if( hasnext ){ pg.totalPageNum = tcp + 1; }else{ pg.totalPageNum = tcp; } }else if( !thn ){ if( !hasnext ){ pg.totalPageNum = tcp; }else if(tcp > ttp){ pg.totalPageNum = tcp + 1; } } /***************** 原 afterRequest 内容结束 ****************/ pg.idata = pg.idata.concat(jsndata); // 第二个参数容器内容为空,则全部添加到容器中 c.lazyAdd.call(pg,emp); // 最后一页的判断必须放在 af.call 后面,因为af 有对totalPageNum进行修改 // setPager 必须放在后面 if(!sub || isFirstSub || pg.isLastSub()){ pg.setPager(); } if( pg.caching ){ pg.$pager.css({ "display" : "block", "height" : 0, "overflow" : "hidden" }) }else if( pg.isLastSub() ){ pg.$pager.css({ "display" : "block", "height" : "auto" }) } pg.pagerVisible = true; }, // 请求分页数据,请求结束后 always 执行 _requestAlways : function (){ var pg = this, c = pg.config; pg.loading = false, pg.$dom.removeClass('woo-loading'), pg.$loadingsm.css('visibility','hidden'); // 执行配置好的 requestAlways 方法 $.isFunction(c.requestAlways) && c.requestAlways(pg,IDX); }, // 请求发起前执行 参数c 表示是否有清空内容容器 _beforeRequest : function (c){ var pg = this, $loadingsm = pg.$loadingsm; pg.$pager.after($loadingsm), Woo.$footer.css("display","none"); // 如果主内容区块有被清空 if(c){ // 内容区loading 进度条展示 pg.$dom.addClass('woo-loading'), $loadingsm.css('visibility','hidden'), // 清除内存 WooTemp 对象,主要是MASNUNITS WOOTEMP && WOOTEMP.reset(), // 清除上一次瀑布流的缓存数据 pg.idata = [], pg.$data = $(null); // 重新开启 TIMERINTERVAL if( TIMERINTERVAL ){ window.clearTimeout(TIMERINTERVAL) } Woo._onscroll() }else{ $loadingsm.css('visibility','visible') } }, /* @说明:获取分页数据 @参数: cp - (Num) 分页页码数 sub - (Bool) 加载subpage 中 direct - (Bool) 中断之前的请求处理,直接进入下一次请求 prepare - (Bool) 是否启动后一页预加载 clear - (Bool) 是否内容容器被清空了 */ _requestData : function (cp,sub,direct,prepare,clear){ var pg = this, c = pg.config, spn = c.subPageNum, arrurl = pg.arrurl, undefined; if( arrurl ){ !prepare && pg._beforeRequest(clear); // 大页码翻页时,检查有没有预加载 if( pg.prepare && pg.prepare[0] == cp ){ pg.requestOver(cp,sub,pg.prepare[1],pg.prepare[2],pg.prepare[3]), pg.prepare = null, // 延迟两秒后执行 always 以便设置 pg.loading=false $({}).delay(100).queue(function (){ pg._requestAlways() }), pg.scrollLoading = false; }else{ var $form = $(arrurl[0]); $.ajax({ type : 'POST', dataType : c.ajaxDataType, cache : typeof DEBUG !== 'undefined' && DEBUG ? false : !!c.ajaxCache, url : typeof DEBUG !== 'undefined' && DEBUG ? '?page='+cp : Woo.getFormAction($form) + cp + arrurl[1], data : Woo.paramForm($form), timeout : 20000, success : function(h){ // 如果是 debug状态,随机取一页测试数据 typeof DEBUG !== 'undefined' && DEBUG && (h = DEBUG_DATA[Math.floor((DEBUG_DATA.length-1)*Math.random())]); if( pg.halting && !direct ) return; if( direct ){ pg.halting = false, pg.$dom.empty(); } // resp = [cont, hasnext, totalcount] // 前两个数值必须有,最后的totalcount 可选 var resp = c.analyzeResponse(h); if(prepare){ pg.prepare = [cp,resp[0],resp[1],resp[2]]; // 准备下一页的图片,预加载图片 var lst = []; $(resp[0]).find('img[srcd]').each(function (i,e){ var $e = $(e); lst.push($e.attr('srcd')); }) Woo.recurseDo(function (a){ new Image().src = a.splice(0,1); return [a]; },[lst],lst.length,200) }else{ pg.requestOver(cp,sub,resp[0],resp[1],resp[2]); } pg.scrollLoading = false; pg._requestAlways(); }, error : function (x,statustext){ if(!prepare){ $('
网络繁忙,点此重试~
') .click(function (e){ e.stopPropagation(), e.preventDefault(), pg._requestData(cp,sub), $(this).remove(); }) .insertAfter(pg.$dom); } pg._requestAlways() } }) // ajax over } } }, /* @说明:是否还有下一大页 */ hasNextUpperPage : function (){ var pg = this; return pg.hasNextUpperPage; }, /* @说明:是否是最后一个子页 */ isLastSub : function (){ var pg = this; return pg.currentPage % pg.config.subPageNum === 0 || pg.currentPage === pg.totalPageNum; }, /* @说明:最后一个子页加载完后执行,显示footer 用 */ showFooter : function (){ var pg = this; pg.$pager.css({"height" : "auto"}), Woo.$footer.css("display","block"), // 移除底部的loading 状态条 pg.$loadingsm.remove(); // 设置翻页器可见 window.setTimeout(function (){ // 结束intervaltimer if( pg.$data.length === 0 && pg.idata.length === 0 ){ window.clearTimeout(TIMERINTERVAL) } },200); // call onOnePageOver pg.config.onOnePageOver(pg, IDX); }, /* @说明:设置pager内容,依赖this.pager 节点 */ setPager : function (){ var pg = this, c = pg.config, cup = pg.currentUpperPage, nn = c.nearbyPageNum, tn = pg.totalPageNum, spn = c.subPageNum, // 翻页器字符串 strPager = '', undefined; tn = Math.floor((tn-.1)/spn) + 1; if( (c.nextMode && cup >= tn || !c.nextMode && cup >= tn) && pg.hasNoMore ){ pg.hasNextUpperPage = false; } if( pg.isLastSub() ){ // 以下是配置普通翻页器的html 字符串 strPager = ['
    ', cup==1 ? '' : '
  • 上一页
  • ' , cup==1 ? '
  • 1
  • ' : '
  • 1
  • ', cup-nn > 2 ? '
  • ' : '', (function (){ var tmps = ''; for(var i=cup-nn; i<=cup+nn; i++){ if( i==cup && i!=1 ){ tmps += '
  • '+i+'
  • '; }else if(i>1 && i<=tn){ tmps += '
  • '+i+'
  • '; } } return tmps })(), cup+nn < tn-1 && !c.nextMode ? '
  • ' : '', cup+nn < tn && !c.nextMode ? '
  • '+tn+'
  • ' : '', cup==tn ? '' : ( c.nextMode ? '
  • ' : '') +'
  • 下一页
  • ', '
'].join(''); pg.$pager.find('.woo-pbr').remove(), pg.$pager.append(strPager); } else{ pg.$pager.find('.woo-pbr').remove(), pg.$pager.append(strPager); } // pager绑定click 事件 if(!pg.isEventSetting){ pg.addEventOnPagerClick(), pg.isEventSetting = true; } var $gonext = Woo.$gonext; $gonext.css('display','block'); if( pg.$pager.find('.woo-pbr').length ){ $gonext.css('visibility', pg.hasNextUpperPage ? 'visible' : 'hidden'); } pg.pagerVisible = true, pg.doLazyAdd(); }, /* @说明:url hash定位 只在firstSub 时改变hash @参数: idt - (Str) pagine 对象的标识字符串 upg - (Num) pagine 对象的 currentUpperpage */ changeHashOnFirstLoad : function (idt,upg){ var pg = this, hash = idt + (upg > 1 ? '-p' + upg : ''), nowhs = H.getHash(); if( (nowhs || pg.isPagerClick) && nowhs !== hash ){ H.setHash(hash); } }, /* @说明:翻页pager 绑定click事件 */ addEventOnPagerClick : function (){ var pg = this; pg.$pager.click(function (e){ var s = e.target; if( s && s.tagName && s.tagName.toLowerCase() != 'a'){ s = $(s).closest('a')[0]; } if( s && s.tagName && s.tagName.toLowerCase() === 'a' && !$(s).closest('.woo-nopagine',pg.$pager.get(0)).length){ e.preventDefault(); e.stopPropagation(); var pto = parseInt(s.innerHTML), dir = s.getAttribute('pdir'); // 用于判断是否用户点击 pg.isPagerClick = true; if(pto){ pg.gotoPage(pto); }else if(dir === 'jump'){ pg.jumpPage(); }else if(dir === 'sub'){ pg.slideSubPage(1); }else if(dir = parseInt(dir)){ pg.slidePage(dir); } } }) }, /* @说明:判断是否触发 lazyAdd @参数 wt - 传入的 window scrollTop 数值 imm - 直接进入 lazyAdd */ doLazyAdd : function (wt,imm){ var pg = this, c = pg.config, wt = wt === undefined ? $W.scrollTop() : wt, dacol = pg.$dom.data('colY'), distance = pg.$pager.offset().top - wt - WH, mx = Math.max.apply(Math,dacol), mi = Math.min.apply(Math,dacol); if( !pg.lazyAdding && pg.pagerVisible && pg.caching && ( imm || distance < c.scrollBias || distance < mx - mi ) ){ c.lazyAdd.call(pg); } }, /* @说明:判断是否触发 slideSubPage */ doLoadNext : function (){ var pg = this, c = pg.config; // 当scrollTop + window窗口内页面可视高度 === more btn的offsetTop 时启动 if( !pg.lazyAdding && !pg.halting && !pg.scrollLoading && pg.pagerVisible && (pg.caching < 2 || !pg.caching) && !pg.isLastSub() ){ pg.scrollLoading = true, pg.slideSubPage(1); } } } /* @说明:Masn 类 */ Woo.Masn = function ($cont,opts){ this.init($cont,opts); } Woo.Masn.prototype = { /* @说明:Masn 类初始化方法 @参数: $cont - (Str) Masn 主容器,可以是dom selector or jquery对象 opts - (Dic) 参数说明详见类实例化的相关代码 */ init: function ($cont,opts){ this.opts = $.extend({}, opts) var masn = this; masn.$dom = $($cont), masn.domInitWidth = masn.$dom.data('domwidth') || 'auto', masn.figure(), masn.arrangeContents(), masn.opts.onFirstArrange(IDX); }, figure : function (){ var masn = this, colY = [], $d = masn.$dom, c = masn.opts, exlen = 0, $cursor = $('
'); $d.css({ "position" : "relative" }); // 计算列宽和列数 masn.colwf = masn.colw = c.columnWidth; if( c.firstColumnWidth ){ masn.colwf = c.firstColumnWidth; } masn.setCols(); // 设置每列的初始高度为0 for( var i=0; i
').removeClass(clss), $d.before($pre); } // indom 为true 时, $data所有单元都已经在dom 树上 var $lame = $data.add(htmlp).removeClass('woo-wait'), $drawer = indom ? $lame.parent() : $pre.append($lame); $htmlp = $drawer.find(c.unit).not('.woo-f,.woo-wait').each(function (i,e){ var $e = $(e), id = $e.data('id'); // 在左(右)侧第一个位置增加占位节点,之前如果有添加过(resize时)则删除 if( (i === 0 && f && !c.rightAlignFirstBlock || i === colc - 1 && f && c.rightAlignFirstBlock) ){ // 计算 minY minI left ars = masn.prePlaceUnit($e, colY, colc, resize, f); minY = ars[0], minI = ars[1], left = ars[2], ht = ars[3], colwf = ars[4], // 要添加的节点外层字符串 addf = '
', strwrap += addf; // 如果是resize 中,并且已经有插入过节点 if( resf ){ $addfc = $drawer.find('.woo-f:first').css({ "left" : left, "top" : minY }); }else{ $addfc = $(addf).append(c.sinkWhat); } mm = i; } // 计算 minY minI left ars = masn.prePlaceUnit($e, colY, colc, resize); minY = ars[0], minI = ars[1], left = ars[2], ht = ars[3], colwf = ars[4], strwrap += '
'; $e.css({ "top" : minY, "left" : left }) .data('ht',ht) .removeClass(function (i,cls){ return 'woo-spcol ' + (cls.match(/(co|sc)\d+/ig) || []).join(' ') }) .addClass((colwf ? 'woo-spcol ' : '')+'sc'+masn.screen+' co'+minI); }) // 遍历结束后保存最终的 colY $d.data('colY',colY); // resf 判断是否resize 中,并且已经插入好节点 if( !resf && f ){ var arrp = $htmlp.toArray(); $htmlp = $(arrp.slice(0,mm).concat($addfc ? $addfc.toArray() : [],arrp.slice(mm))) } $pre.empty(); return [$(strwrap),$htmlp]; } } $.Woo = Woo; })(window)