Authored by htoooth

refactor

@@ -23,13 +23,15 @@ const CHANNEL = { @@ -23,13 +23,15 @@ const CHANNEL = {
23 }; 23 };
24 24
25 const _getChannel = (req, res) => { 25 const _getChannel = (req, res) => {
26 - const channel = req.cookies._Channel || ''; 26 + let channel = req.cookies._Channel;
27 27
28 if (!channel) { 28 if (!channel) {
29 res.cookie('_Channel', CHANNEL.boys, { 29 res.cookie('_Channel', CHANNEL.boys, {
30 domain: '.yohobuy.com', 30 domain: '.yohobuy.com',
31 maxAge: moment.duration(300, 'days').seconds() 31 maxAge: moment.duration(300, 'days').seconds()
32 }); 32 });
  33 +
  34 + channel = 'boys'; // 设置默认值
33 } 35 }
34 36
35 return channel; 37 return channel;
@@ -47,30 +49,25 @@ const _getGender = (channel) => { @@ -47,30 +49,25 @@ const _getGender = (channel) => {
47 }; 49 };
48 50
49 /** 51 /**
50 - * 渲染商品详情 52 + * 首屏渲染商品详情
51 */ 53 */
52 const showMain = (req, res, next) => { 54 const showMain = (req, res, next) => {
53 let pid = req.params[0]; 55 let pid = req.params[0];
54 - let gid = req.params[1];  
55 let channel = _getChannel(req, res); 56 let channel = _getChannel(req, res);
56 let gender = _getGender(channel); 57 let gender = _getGender(channel);
57 58
58 - let saveCurrentGoodsInCookies = _.partial(service.saveRecentGoodInCookies,  
59 - req.cookies._browse,  
60 - req.cookies._browseskn,  
61 - res  
62 - );  
63 -  
64 - return service.showMainAsync({  
65 - pid: pid,  
66 - gid: gid,  
67 - channel: channel,  
68 - gender: gender, 59 + const nullUserInfo = {
69 uid: null, 60 uid: null,
70 isStudent: null, 61 isStudent: null,
71 vipLevel: null, 62 vipLevel: null,
72 - saveInCookies: saveCurrentGoodsInCookies  
73 - }).then(result=> { 63 + saveInCookies: null
  64 + };
  65 +
  66 + return service.showMainAsync(Object.assign({
  67 + pid: pid,
  68 + channel: channel,
  69 + gender: gender
  70 + }, nullUserInfo)).then(result=> {
74 return res.render('product/detail', Object.assign({ 71 return res.render('product/detail', Object.assign({
75 module: 'product', 72 module: 'product',
76 page: 'detail', 73 page: 'detail',
@@ -84,6 +81,47 @@ const showMain = (req, res, next) => { @@ -84,6 +81,47 @@ const showMain = (req, res, next) => {
84 81
85 }; 82 };
86 83
  84 +const detailHeader = (req, res, next) => {
  85 + let pid = req.query.productId || 0;
  86 + let uid = req.user.uid || 0;
  87 + let vipLevel = detailHelper.vipLevel(req.user.vip);
  88 + let dataMd5 = req.query.md5 || 0;
  89 +
  90 + let saveCurrentGoodsInCookies = _.partial(service.saveRecentGoodInCookies,
  91 + req.cookies._browseskn,
  92 + res
  93 + );
  94 +
  95 + return service.getDetailHeader(pid, uid, req.user.isStudent, vipLevel, dataMd5, saveCurrentGoodsInCookies)
  96 + .then((result) => {
  97 + if (result.code === 200) {
  98 + return res.render('product/detail-header', Object.assign({layout: false}, result.data));
  99 + } else {
  100 + return res.status(204).end();
  101 + }
  102 + }).catch(next);
  103 +};
  104 +
  105 +const detailReturn = (req, res, next) => {
  106 + let skn = req.query.skn || 0;
  107 +
  108 + if (!skn) {
  109 + return {
  110 + code: 400,
  111 + message: '商品数据出错'
  112 + };
  113 + }
  114 +
  115 + return service.saleReturn(skn).then(result => {
  116 + return res.json({
  117 + code: 200,
  118 + data: {
  119 + result: result
  120 + }
  121 + });
  122 + }).catch(next);
  123 +};
  124 +
87 /** 125 /**
88 * 获取热区图 126 * 获取热区图
89 */ 127 */
@@ -182,22 +220,6 @@ const createConsult = (req, res, next) => { @@ -182,22 +220,6 @@ const createConsult = (req, res, next) => {
182 } 220 }
183 }; 221 };
184 222
185 -const detailHeader = (req, res, next) => {  
186 - let pid = req.query.productId || 0;  
187 - let uid = req.user.uid || 0;  
188 - let vipLevel = detailHelper.vipLevel(req.user.vip);  
189 - let dataMd5 = req.query.md5 || 0;  
190 -  
191 - // service.getDetailHeader(pid, uid, req.user.isStudent, vipLevel, dataMd5).then((result) => {  
192 - // if (result.code === 200) {  
193 - // return res.render('product/detail-header', Object.assign({layout: false}, result.data));  
194 - // } else {  
195 - // return res.status(204).end();  
196 - // }  
197 - // }).catch(next);  
198 -  
199 - return res.status(204).end();  
200 -};  
201 223
202 module.exports = { 224 module.exports = {
203 showMain, 225 showMain,
@@ -205,8 +227,8 @@ module.exports = { @@ -205,8 +227,8 @@ module.exports = {
205 indexComment, 227 indexComment,
206 indexConsult, 228 indexConsult,
207 createConsult, 229 createConsult,
208 - productHeader: detailHeader  
209 - 230 + productHeader: detailHeader,
  231 + detailReturn
210 }; 232 };
211 233
212 234
@@ -486,25 +486,16 @@ function _getSortNavAsync(smallSortId, gender) { @@ -486,25 +486,16 @@ function _getSortNavAsync(smallSortId, gender) {
486 } 486 }
487 487
488 // 保存在 gids 和 skns ,最近流览功能 488 // 保存在 gids 和 skns ,最近流览功能
489 -const saveRecentGoodInCookies = (oldGids, oldSkns, res, addGids, addSkns) => {  
490 - oldGids = (oldGids || '').split(',');  
491 - oldSkns = (oldSkns || '').split(',');  
492 - addSkns = `${addSkns}-${addGids}`; 489 +const saveRecentGoodInCookies = (oldSkns, res, addSkns) => {
  490 + oldSkns = oldSkns || [];
493 491
494 - _.remove(oldGids, addGids);  
495 _.remove(oldSkns, addSkns); 492 _.remove(oldSkns, addSkns);
496 493
497 - oldGids.unshift(addGids);  
498 oldSkns.unshift(addSkns); 494 oldSkns.unshift(addSkns);
499 495
500 - res.cookie('_browse', oldGids.splice(0, 30).join(','), {  
501 - maxAge: 2000000000,  
502 - domain: 'yohobuy.com'  
503 - });  
504 -  
505 res.cookie('_browseskn', oldSkns.splice(0, 30).join(','), { 496 res.cookie('_browseskn', oldSkns.splice(0, 30).join(','), {
506 maxAge: 2000000000, 497 maxAge: 2000000000,
507 - domain: 'yohobuy.com' 498 + domain: '.yohobuy.com'
508 }); 499 });
509 }; 500 };
510 501
@@ -1052,7 +1043,7 @@ const _getSeoByGoodsInfo = (goodsInfo, navs) => { @@ -1052,7 +1043,7 @@ const _getSeoByGoodsInfo = (goodsInfo, navs) => {
1052 * @param origin Object 原始数据 1043 * @param origin Object 原始数据
1053 * @return result Object 格式化数据 1044 * @return result Object 格式化数据
1054 */ 1045 */
1055 -const _detailDataPkg = (origin, uid, vipLevel) => { 1046 +const _detailDataPkg = (origin, uid, vipLevel, cookies) => {
1056 return co(function*() { 1047 return co(function*() {
1057 let result = {}; // 结果输出 1048 let result = {}; // 结果输出
1058 let md5 = origin.md5; 1049 let md5 = origin.md5;
@@ -1286,19 +1277,25 @@ const _detailDataPkg = (origin, uid, vipLevel) => { @@ -1286,19 +1277,25 @@ const _detailDataPkg = (origin, uid, vipLevel) => {
1286 } 1277 }
1287 } 1278 }
1288 1279
  1280 + // 最近浏览功能 ,限量商品不加入到最近浏览
  1281 + if (!_.has(result, 'fashionTopGoods')) {
  1282 + cookies && cookies(_.get(result, 'skn', ''));
  1283 + }
  1284 +
1289 return { 1285 return {
1290 goodsInfo: result, 1286 goodsInfo: result,
1291 banner: _.isEmpty(bandInfo) ? null : bandInfo, 1287 banner: _.isEmpty(bandInfo) ? null : bandInfo,
1292 - statGoodsInfo: statGoodsInfo 1288 + statGoodsInfo: statGoodsInfo,
  1289 + latestWalk: 5 // 只显示5个
1293 }; 1290 };
1294 })(); 1291 })();
1295 }; 1292 };
1296 1293
1297 -const getDetailHeader = (pid, uid, isStudent, vipLevel, dataMd5) => {  
1298 - let currentUserProductInfo = _.partial(_detailDataPkg, _, uid, vipLevel); 1294 +const getDetailHeader = (pid, uid, isStudent, vipLevel, dataMd5, cookie) => {
  1295 + let currentUserProductInfo = _.partial(_detailDataPkg, _, uid, vipLevel, cookie);
1299 1296
1300 return productAPI.getProductAsync(pid, uid, isStudent, vipLevel) 1297 return productAPI.getProductAsync(pid, uid, isStudent, vipLevel)
1301 - .then(result => currentUserProductInfo(result)) 1298 + .then(currentUserProductInfo)
1302 .then((result) => { 1299 .then((result) => {
1303 if (result.goodsInfo.md5 !== dataMd5 || uid) { 1300 if (result.goodsInfo.md5 !== dataMd5 || uid) {
1304 return { 1301 return {
@@ -1314,16 +1311,20 @@ const getDetailHeader = (pid, uid, isStudent, vipLevel, dataMd5) => { @@ -1314,16 +1311,20 @@ const getDetailHeader = (pid, uid, isStudent, vipLevel, dataMd5) => {
1314 }); 1311 });
1315 }; 1312 };
1316 1313
  1314 +const saleReturn = (skn) => {
  1315 + return productAPI.isSupportReturnedSale(skn).then(result => _.get(result, `data.${skn}`, 'N') === 'N' ? 'Y' : 'N');
  1316 +};
  1317 +
1317 /** 1318 /**
1318 * 获取某一个商品详情主页面 1319 * 获取某一个商品详情主页面
1319 */ 1320 */
1320 const showMainAsync = (data) => { 1321 const showMainAsync = (data) => {
1321 return co(function * () { 1322 return co(function * () {
1322 - let currentUserProductInfo = _.partial(_detailDataPkg, _, data.uid, data.vipLevel); 1323 + let curUserProduct = _.partial(_detailDataPkg, _, data.uid, data.vipLevel, data.gid, data.saveInCookies);
1323 1324
1324 // 获取并处理商品基本信息 1325 // 获取并处理商品基本信息
1325 let productInfo = yield productAPI.getProductAsync(data.pid, data.uid, data.isStudent, data.vipLevel) 1326 let productInfo = yield productAPI.getProductAsync(data.pid, data.uid, data.isStudent, data.vipLevel)
1326 - .then(currentUserProductInfo); 1327 + .then(curUserProduct);
1327 1328
1328 if (_.isEmpty(productInfo) || _.isEmpty(productInfo.goodsInfo)) { 1329 if (_.isEmpty(productInfo) || _.isEmpty(productInfo.goodsInfo)) {
1329 return Promise.reject({ 1330 return Promise.reject({
@@ -1334,7 +1335,7 @@ const showMainAsync = (data) => { @@ -1334,7 +1335,7 @@ const showMainAsync = (data) => {
1334 let requestData = yield Promise.all([ 1335 let requestData = yield Promise.all([
1335 _getSortNavAsync(productInfo.goodsInfo.smallSortId, data.gender), // 导航 1336 _getSortNavAsync(productInfo.goodsInfo.smallSortId, data.gender), // 导航
1336 HeaderModel.requestHeaderData(data.channel), // 头部数据 1337 HeaderModel.requestHeaderData(data.channel), // 头部数据
1337 - productAPI.isSupportReturnedSale(productInfo.goodsInfo.skn), // 退换货 1338 + productAPI.isSupportReturnedSale(productInfo.goodsInfo.skn), // 退换货 TODO:
1338 _getProductIntroAsync(productInfo.goodsInfo.productId, productInfo.goodsInfo.skn) // 商品详细介绍 1339 _getProductIntroAsync(productInfo.goodsInfo.productId, productInfo.goodsInfo.skn) // 商品详细介绍
1339 ]); 1340 ]);
1340 1341
@@ -1375,13 +1376,6 @@ const showMainAsync = (data) => { @@ -1375,13 +1376,6 @@ const showMainAsync = (data) => {
1375 [{name: productInfo.goodsInfo.name}] 1376 [{name: productInfo.goodsInfo.name}]
1376 ); 1377 );
1377 1378
1378 - // 最近浏览功能 ,限量商品不加入到最近浏览  
1379 - if (!_.has(productInfo, 'goodsInfo.fashionTopGoods')) {  
1380 - data.saveInCookies(data.gid, _.get(productInfo, 'goodsInfo.skn', ''));  
1381 - }  
1382 -  
1383 - // 只显示5个  
1384 - result.detail.latestWalk = 5;  
1385 1379
1386 return result; 1380 return result;
1387 })(); 1381 })();
@@ -1395,5 +1389,6 @@ module.exports = { @@ -1395,5 +1389,6 @@ module.exports = {
1395 showMainAsync: showMainAsync, // 获取某一个商品详情主页面 1389 showMainAsync: showMainAsync, // 获取某一个商品详情主页面
1396 indexHotAreaAsync: hotAreaService.indexAsync, // 获取某一个商品的热区数据 1390 indexHotAreaAsync: hotAreaService.indexAsync, // 获取某一个商品的热区数据
1397 saveRecentGoodInCookies, // 保存最近的商品 1391 saveRecentGoodInCookies, // 保存最近的商品
1398 - getDetailHeader 1392 + getDetailHeader,
  1393 + saleReturn
1399 }; 1394 };
@@ -59,6 +59,8 @@ router.post('/detail/consult', auth, detail.createConsult);// 创建咨询 @@ -59,6 +59,8 @@ router.post('/detail/consult', auth, detail.createConsult);// 创建咨询
59 router.get('/detail/hotarea', detail.indexHotArea);// 商品热区 59 router.get('/detail/hotarea', detail.indexHotArea);// 商品热区
60 router.post('/index/favoriteBrand', favorite.changeFavoriteBrand);// 收藏品牌 60 router.post('/index/favoriteBrand', favorite.changeFavoriteBrand);// 收藏品牌
61 router.post('/item/togglecollect', favorite.collectProduct); // 收藏商品 61 router.post('/item/togglecollect', favorite.collectProduct); // 收藏商品
  62 +router.get('/detail/header', detail.productHeader); // 价格数据重新获取接口
  63 +router.get('/detail/return', detail.detailReturn);// 特殊商品退换货
62 64
63 // 搜索 65 // 搜索
64 router.get('/search/index', search.index); 66 router.get('/search/index', search.index);
@@ -23,7 +23,8 @@ @@ -23,7 +23,8 @@
23 {{> common/path-nav}} 23 {{> common/path-nav}}
24 24
25 {{# goodsInfo}} 25 {{# goodsInfo}}
26 - <div class="main clearfix" data-skn="{{skn}}" data-id="{{productId}}"> 26 + <div class="main clearfix" data-skn="{{skn}}" data-id="{{productId}}" data-md5="{{md5}}"
  27 + data-skn="{{skn}}">
27 <div class="pull-left imgs clearfix"> 28 <div class="pull-left imgs clearfix">
28 <div class="pull-left img"> 29 <div class="pull-left img">
29 <div class="tags clearfix"> 30 <div class="tags clearfix">
@@ -540,12 +541,18 @@ @@ -540,12 +541,18 @@
540 <span class="title cur">商品详情 DETAILS</span> 541 <span class="title cur">商品详情 DETAILS</span>
541 </p> 542 </p>
542 <div id="details-html" class="details-html"> 543 <div id="details-html" class="details-html">
  544 + <div class="lazy-load-object">
  545 + <textarea class="datalazyload" style="visibility: hidden;">
  546 + <script>fetchHotArea();</script>
  547 + </textarea>
  548 + </div>
543 {{{details}}} 549 {{{details}}}
544 </div> 550 </div>
545 </div> 551 </div>
546 552
547 {{# consultComment}} 553 {{# consultComment}}
548 <div class="consult-comment info-block"> 554 <div class="consult-comment info-block">
  555 +
549 <p class="block-title"> 556 <p class="block-title">
550 <span class="title">顾客咨询(<em class="consult-num">0</em></span> 557 <span class="title">顾客咨询(<em class="consult-num">0</em></span>
551 <span class="sep">|</span> 558 <span class="sep">|</span>
@@ -599,6 +606,14 @@ @@ -599,6 +606,14 @@
599 </p> 606 </p>
600 </div> 607 </div>
601 </div> 608 </div>
  609 +
  610 + <div class="lazy-load-object">
  611 + <textarea class="datalazyload" style="visibility: hidden;">
  612 + <script>fetchComment();
  613 + fetchReturn();</script>
  614 + </textarea>
  615 + </div>
  616 +
602 </div> 617 </div>
603 {{/ consultComment}} 618 {{/ consultComment}}
604 619
@@ -635,11 +650,8 @@ @@ -635,11 +650,8 @@
635 </div> 650 </div>
636 </div> 651 </div>
637 652
638 - {{#if supportSaleReturnedService}}  
639 <div class="support-saleReturned-service"></div> 653 <div class="support-saleReturned-service"></div>
640 - {{^}}  
641 - <div class="not-support-saleReturned-service"></div>  
642 - {{/if}} 654 +
643 655
644 <div class="service"></div> 656 <div class="service"></div>
645 {{#if latestWalk}} 657 {{#if latestWalk}}
@@ -724,7 +736,8 @@ @@ -724,7 +736,8 @@
724 736
725 (function() { 737 (function() {
726 var mvl = document.createElement('script'); 738 var mvl = document.createElement('script');
727 - mvl.type = 'text/javascript'; mvl.async = true; 739 + mvl.type = 'text/javascript';
  740 + mvl.async = true;
728 mvl.src = ('https:' == document.location.protocol ? 'https://static-ssl.mediav.com/mvl.js' : 'http://static.mediav.com/mvl.js'); 741 mvl.src = ('https:' == document.location.protocol ? 'https://static-ssl.mediav.com/mvl.js' : 'http://static.mediav.com/mvl.js');
729 var s = document.getElementsByTagName('script')[0]; 742 var s = document.getElementsByTagName('script')[0];
730 s.parentNode.insertBefore(mvl, s); 743 s.parentNode.insertBefore(mvl, s);
  1 +/* eslint-disable */
  2 +/**
  3 + * Created by TaoHuang on 2016/10/10.
  4 + */
  5 +function dataLazyLoad(doc) {
  6 +
  7 + // 兼容低版本 IE
  8 + Function.prototype.bind = Function.prototype.bind || function(context) {
  9 + var that = this;
  10 + return function() {
  11 + return that.apply(context, arguments);
  12 + };
  13 + };
  14 +
  15 + // 工具方法 begin
  16 + var Util = {
  17 + getElementsByClassName: function(cls) {
  18 + if (doc.getElementsByClassName) {
  19 + return doc.getElementsByClassName(cls);
  20 + }
  21 +
  22 + var o = doc.getElementsByTagName("*"),
  23 + rs = [];
  24 +
  25 + for (var i = 0, t, len = o.length; i < len; i++) {
  26 + (t = o[i]) && ~t.className.indexOf(cls) && rs.push(t);
  27 + }
  28 +
  29 + return rs;
  30 + },
  31 + addEvent: function(ele, type, fn) {
  32 + ele.attachEvent ? ele.attachEvent("on" + type, fn) : ele.addEventListener(type, fn, false);
  33 + },
  34 + removeEvent: function(ele, type, fn) {
  35 + ele.detachEvent ? ele.detachEvent("on" + type, fn) : ele.removeEventListener(type, fn, false);
  36 + },
  37 + getPos: function(ele) {
  38 + var pos = {
  39 + x: 0,
  40 + y: 0
  41 + };
  42 +
  43 + while (ele.offsetParent) {
  44 + pos.x += ele.offsetLeft;
  45 + pos.y += ele.offsetTop;
  46 + ele = ele.offsetParent;
  47 + }
  48 +
  49 + return pos;
  50 + },
  51 + getViewport: function() {
  52 + var html = doc.documentElement;
  53 +
  54 + return {
  55 + w: !window.innerWidth ? html.clientHeight : window.innerWidth,
  56 + h: !window.innerHeight ? html.clientHeight : window.innerHeight
  57 + };
  58 + },
  59 + getScrollHeight: function() {
  60 + html = doc.documentElement, bd = doc.body;
  61 + return Math.max(window.pageYOffset || 0, html.scrollTop, bd.scrollTop);
  62 + },
  63 + getEleSize: function(ele) {
  64 + return {
  65 + w: ele.offsetWidth,
  66 + h: ele.offsetHeight
  67 + };
  68 + }
  69 + };
  70 + // 工具方法 end
  71 +
  72 + return {
  73 + threshold: 0, // {number} 阈值,预加载高度,单位(px)
  74 + els: null, // {Array} 延迟加载元素集合(数组)
  75 + fn: null, // {Function} scroll、resize、touchmove 所绑定方法,即为 pollTextareas()
  76 +
  77 + evalScripts: function(code) {
  78 + var head = doc.getElementsByClassName("yoho-footer")[0],
  79 + js = doc.createElement("script");
  80 +
  81 + js.text = code;
  82 + head.appendChild(js, head.firstChild);
  83 + head.removeChild(js);
  84 + },
  85 +
  86 + evalStyles: function(code) {
  87 + var head = doc.getElementsByTagName("head")[0],
  88 + css = doc.createElement("style");
  89 +
  90 + css.type = "text/css";
  91 +
  92 + try {
  93 + css.appendChild(doc.createTextNode(code));
  94 + } catch (e) {
  95 + css.styleSheet.cssText = code;
  96 + }
  97 +
  98 + head.appendChild(css);
  99 + },
  100 +
  101 + extractCode: function(str, isStyle) {
  102 + var cata = isStyle ? "style" : "script",
  103 + scriptFragment = "<" + cata + "[^>]*>([\\S\\s]*?)</" + cata + "\\s*>",
  104 + matchAll = new RegExp(scriptFragment, "img"),
  105 + matchOne = new RegExp(scriptFragment, "im"),
  106 + matchResults = str.match(matchAll) || [],
  107 + ret = [];
  108 +
  109 + for (var i = 0, len = matchResults.length; i < len; i++) {
  110 + var temp = (matchResults[i].match(matchOne) || ["", ""])[1];
  111 + temp && ret.push(temp);
  112 + }
  113 + return ret;
  114 + },
  115 +
  116 + decodeHTML: function(str) {
  117 + return str.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&")
  118 + .replace(/&lt;/g, '<').replace(/&gt;/g, '>');
  119 + },
  120 +
  121 + insert: function(ele) {
  122 + var parent = ele.parentNode,
  123 + txt = this.decodeHTML(ele.innerHTML),
  124 + matchStyles = this.extractCode(txt, true),
  125 + matchScripts = this.extractCode(txt);
  126 +
  127 + parent.innerHTML = txt
  128 + .replace(new RegExp("<script[^>]*>([\\S\\s]*?)</script\\s*>", "img"), "")
  129 + .replace(new RegExp("<style[^>]*>([\\S\\s]*?)</style\\s*>", "img"), "");
  130 +
  131 + if (matchStyles.length) {
  132 + for (var i = matchStyles.length; i--;) {
  133 + this.evalStyles(matchStyles[i]);
  134 + }
  135 + }
  136 +
  137 +
  138 + // 如果延迟部分需要做 loading 效果
  139 + parent.className = parent.className.replace("loading", "");
  140 +
  141 + if (matchScripts.length) {
  142 + for (var i = 0, len = matchScripts.length; i < len; i++) {
  143 + this.evalScripts(matchScripts[i]);
  144 + }
  145 + }
  146 + },
  147 +
  148 + inView: function(ele) {
  149 + var top = Util.getPos(ele).y
  150 + , viewVal = Util.getViewport().h
  151 + , scrollVal = Util.getScrollHeight()
  152 + , eleHeight = Util.getEleSize(ele).h;
  153 +
  154 + if (top >= scrollVal - eleHeight - this.threshold && top <= scrollVal + viewVal + this.threshold) {
  155 + return true;
  156 + }
  157 +
  158 + return false;
  159 + },
  160 +
  161 + pollTextareas: function() {
  162 + // 需延迟加载的元素已经全部加载完
  163 + if (!this.els.length) {
  164 + Util.removeEvent(window, "scroll", this.fn);
  165 + Util.removeEvent(window, "resize", this.fn);
  166 + Util.removeEvent(doc.body, "touchMove", this.fn);
  167 + return;
  168 + }
  169 +
  170 + // 判断是否需要加载
  171 + for (var i = this.els.length; i--;) {
  172 + var ele = this.els[i];
  173 +
  174 + if (!this.inView(ele)) {
  175 + continue;
  176 + }
  177 +
  178 + this.insert(ele);
  179 + this.els.splice(i, 1);
  180 + }
  181 + },
  182 +
  183 + init: function(config) {
  184 + var cls = config.cls;
  185 + this.threshold = config.threshold ? config.threshold : 0;
  186 +
  187 + this.els = Array.prototype.slice.call(Util.getElementsByClassName(cls));
  188 + this.fn = this.pollTextareas.bind(this);
  189 +
  190 + this.fn();
  191 + Util.addEvent(window, "scroll", this.fn);
  192 + Util.addEvent(window, "resize", this.fn);
  193 + Util.addEvent(doc.body, "touchMove", this.fn);
  194 + }
  195 + };
  196 +}
  197 +
  198 +module.exports = dataLazyLoad;
  199 +
  200 +/**
  201 + * demo
  202 + * datalazyload.init({
  203 + * cls: "datalazyload", // 需要延迟加载的类,即 textarea 的类名
  204 + * threshold: 100 // 距离底部多高,进行延迟加载的阈值
  205 + * });
  206 + */
@@ -11,13 +11,15 @@ @@ -11,13 +11,15 @@
11 11
12 var $ = require('yoho-jquery'), 12 var $ = require('yoho-jquery'),
13 lazyLoad = require('yoho-jquery-lazyload'), 13 lazyLoad = require('yoho-jquery-lazyload'),
  14 + dataLazyLoad = require('../plugins/lazy-load')(document),
14 Handlebars = require('yoho-handlebars'); 15 Handlebars = require('yoho-handlebars');
15 16
16 var bindEvent = $.Callbacks(); // eslint-disable-line 17 var bindEvent = $.Callbacks(); // eslint-disable-line
17 18
18 var $main = $('.main'), 19 var $main = $('.main'),
19 id = $main.data('id'), 20 id = $main.data('id'),
20 - md5 = $main.data('md5'); 21 + md5 = $main.data('md5'),
  22 + skn = $main.data('skn');
21 23
22 var SLIDETIME = 200; 24 var SLIDETIME = 200;
23 25
@@ -27,6 +29,8 @@ var colTxt = { @@ -27,6 +29,8 @@ var colTxt = {
27 hover: '取消收藏' 29 hover: '取消收藏'
28 }; 30 };
29 31
  32 +var $saleReturn = $('#saleReturn');
  33 +
30 bindEvent.add(function() { 34 bindEvent.add(function() {
31 var $imgShow = $('#img-show'), 35 var $imgShow = $('#img-show'),
32 $thumbs = $('#thumbs > .thumb-wrap'); 36 $thumbs = $('#thumbs > .thumb-wrap');
@@ -549,13 +553,15 @@ $('.after-service-switch').click(function() { @@ -549,13 +553,15 @@ $('.after-service-switch').click(function() {
549 }); 553 });
550 554
551 // 商品详情区的热点 555 // 商品详情区的热点
552 -$.ajax({ 556 +
  557 +function fetchHotArea() {
  558 + $.ajax({
553 type: 'GET', 559 type: 'GET',
554 url: '/product/detail/hotarea', 560 url: '/product/detail/hotarea',
555 data: { 561 data: {
556 productId: id 562 productId: id
557 } 563 }
558 -}).then(function(html) { 564 + }).then(function(html) {
559 $('#details-html').prepend(html); 565 $('#details-html').prepend(html);
560 566
561 // 修正热区尺寸使居中 567 // 修正热区尺寸使居中
@@ -569,13 +575,19 @@ $.ajax({ @@ -569,13 +575,19 @@ $.ajax({
569 }, function() { 575 }, function() {
570 $(this).removeClass('hover'); 576 $(this).removeClass('hover');
571 }); 577 });
572 -}); 578 + });
  579 +}
573 580
574 -// 商品详情懒加载 581 +window.fetchHotArea = fetchHotArea;
  582 +
  583 +// 商品详情图片懒加载
575 lazyLoad($('#details-html img')); 584 lazyLoad($('#details-html img'));
576 585
  586 +// 数据懒加载
  587 +dataLazyLoad.init({cls: 'datalazyload', threshold: -50});
  588 +
577 // 咨询和评价 589 // 咨询和评价
578 -(function() { 590 +function fetchComment() {
579 var commentPage = 1, 591 var commentPage = 1,
580 consultPage = 1; 592 consultPage = 1;
581 593
@@ -762,7 +774,28 @@ lazyLoad($('#details-html img')); @@ -762,7 +774,28 @@ lazyLoad($('#details-html img'));
762 774
763 loadComments(); 775 loadComments();
764 loadConsults(); 776 loadConsults();
765 -}()); 777 +}
  778 +
  779 +window.fetchComment = fetchComment;
  780 +
  781 +// 特殊商品退换货
  782 +function fetchReturn() {
  783 + return $.ajax({
  784 + type: 'GET',
  785 + url: '/product/detail/return',
  786 + data: {
  787 + skn: skn
  788 + }
  789 + }).then(function(result) {
  790 + if (result.code === 200) {
  791 + if (result.data.result === 'N') {
  792 + $saleReturn.removeClass().addClass('not-support-saleReturned-service');
  793 + }
  794 + }
  795 + });
  796 +}
  797 +
  798 +window.fetchReturn = fetchReturn;
766 799
767 // 首屏加载,绑定事件 800 // 首屏加载,绑定事件
768 bindEvent.fire(); 801 bindEvent.fire();