// ==UserScript==
// @name Xianyu Page Turning By AJAX
// @namespace https://greasyfork.org/zh-CN/users/6065-hatn
// @version 0.1.5
// @description 闲鱼: 搜索列表改无刷新(预读)翻页:双击【←→】键快速翻页
// @icon http://www.gravatar.com/avatar/10670da5cbd7779dcb70c28594abbe56?r=PG&s=92&default=identicon
// @include *2.taobao.com/list/list.htm*
// @require http://cdn.staticfile.org/jquery/2.1.1-rc2/jquery.min.js
// @copyright 2016, hatn
// @author hatn
// @run-at document-end
// @grant0 GM_xmlhttpRequest
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// ==/UserScript==
/**
*
* 功能:闲鱼 搜索列表改无刷新(预读)翻页
*
* 使用说明:
* 1、双击 【←→】按键 快速翻页(上/下一页);
* 2、原翻页方式改为无刷新方式:动态替换/载入 翻页内容;
* 3、预读成功的页码数变为绿色。
*
*/
/* ######### 参数设置 S ######### */
var config = {
act_type: 1, // 加载模式 [1]底部自动载入(默认) [0]翻页
keyboard_flag: 1, // 监听双击键盘事件 [1]开启(默认) [0]关闭
scroll_time: 600 // act_type = 0 时生效,滚动到顶部的动画时长 默认600毫秒
};
/* ######### 参数设置 E ######### */
var AliObj = {
/* 数据集 */
DATA: {
config: {}, // 参数配置
/* 默认配置 */
defaultCfg: {
act_type: 1,
keyboard_flag: 1,
scroll_time: 600
},
/* 双击按键参数 */
keyData: {
timenow: 0, // 上一按键时间
preKey: null, // 记忆前一按键
keepTime: 400, // 双击间隔
},
/* 页数信息 */
pageData: {
pageCurr: 1,
pageNext: 2,
pagePre: null,
pageTotal: null,
pagePreReadingData: {}, // 格式 {"2": {"list": domObj, "pagelist": domObj, "page": pageNum}, "3": {...}, ...}
},
},
/* 初始化 */
init: function (config) {
var s = this;
s.setParam(config);
s.band();
s.addHtmlCss();
s.autoPreReading();
console.log('log: Xianyu Page Turning By AJAX, Run...');
},
/* 启动器 */
launcher: function (config) {
var s = this;
var times = 10;
var ii = 0;
var preTimer = setInterval(function () {
++ii;
var selector0 = '.pagination';
var selector1 = '.footer-bd';
if ($(selector1).length > 0) {
window.clearInterval(preTimer);
console.log('log: Try ' + ii + ' times !');
if ($(selector0).length < 1) {
console.log('log: No pagelist !');
return false; // 当前页面无商品或只有一页
}
s.init(config);
return true;
}
if (--times < 0) {
window.clearInterval(preTimer) + console.log('err: Time out!');
}
}, 600);
},
/* 事件绑定 */
band: function () {
var s = this, config = s.DATA.config;
config.keyboard_flag == 1 && $(window).on('keyup', function (event) {
var keyCode = event.keyCode;
if (event.type == 'keyup') {
var double = s.doubleClick(keyCode);
if (double == false) return false; // 非双击 不作响应
if (keyCode == '39') { // 右方向键 下一页
s.pageTurning('next');
} else if (keyCode == '37') {
s.pageTurning('pre'); // 左方向键 上一页
}
}
});
// 页码点击事件
$(document).on('click', '#J_Pages a', function(event) {
event.preventDefault(); // 阻止 默认行为
event.stopPropagation(); // 阻止 事件冒泡
var val = $(this).text();
//alert('miaode: ' + val);
s.pageTurning(val);
return false;
});
// 滚动条 · 底部自动载入
var scroll_flag = true; // 防重复载入标识
config.act_type == 1 && $(window).scroll(function() {
if (!scroll_flag) return false;
var scrollTop = $(this).scrollTop();
var scrollHeight = $(document).height();
var windowHeight = $(this).height();
if (scrollTop + windowHeight == scrollHeight) {
scroll_flag = false;
s.pageTurning('next');
scroll_flag = true;
}
});
},
/* 注入css */
addHtmlCss: function() {
var insertStr = '<style id="other-style">.save-flag{color:#8ddc90 !important;}.pre-reading{position: absolute; left: 10000px;top: -10000px;}</style>';
$(insertStr).appendTo($('body'));
},
/* 自动预读 */
autoPreReading: function() {
var s = this;
s.dealPageInfo();
s.preReading();
},
/* 参数读取 */
setParam: function (config) {
var s = this;
config = typeof config == 'object' ? config : {};
$.extend(s.DATA.defaultCfg, config);
s.dataMgr('get');
//s.cfg = {};
//s.dataMgr('set');
},
/* 页码处理 */
dealPageInfo: function() {
var s = this, pageData = s.DATA.pageData;
var totalStr = $('#J_Pages span.paginator-count:eq(0)').text();
var count_res = preg_match_all(/\d+/g, totalStr, 'B');
pageData.pageTotal = count_res ? parseInt(count_res[0][0]) : 2;
pageData.pageCurr = parseInt($('#J_Pages span.paginator-curr:eq(0)').text());
pageData.pagePre = pageData.pageCurr > 1 ? pageData.pageCurr - 1 : null;
pageData.pageNext = pageData.pageCurr == pageData.pageTotal ? null : pageData.pageCurr + 1;
},
/* 预读当前页码 */
preReading: function() {
var s = this;
var $page_arr = $('#J_Pages a').not('.paginator-pre, .paginator-next');
var $tmp, pageNum, pre_arr = [], pid, href;
var pageCache = s.DATA.pageData.pagePreReadingData;
// 保存当前页面 内容
var curr = s.DATA.pageData.pageCurr;
if (typeof pageCache[curr] == 'undefined') {
var content_c = $('#J_ItemListsContainer ul:eq(0)')[0].outerHTML;
var plist_c = $('div.pagination div.wrapper:eq(0)')[0].outerHTML;
pageCache[curr] = {"list": $(content_c), "pageList": $(plist_c), "page": curr};
}
$page_arr.each(function() {
$tmp = $(this);
pageNum = parseInt($tmp.text());
if (typeof pageCache[pageNum] == 'undefined') {
href = $tmp.attr('href');
pid = 'page-pid-' + pageNum;
$tmp[0].id = pid;
pre_arr.push([pageNum, href, pid]);
} else { // 已缓存的 页码变色操作
$tmp.addClass('save-flag'); // #8ddc90
}
});
if (pre_arr.length > 0) dealPrePage(pre_arr, pageCache);
// 预读并保存
function dealPrePage(pre_arr, pageCache) {
var tmp, $body = $('body');
for (var i in pre_arr) {
tmp = pre_arr[i];
// 外套闭包 防止tmp冲突
(function(_tmp) {
var tmp = _tmp, content, plist, $content;
$.get(tmp[1], function(data, status) {
content = $('#J_ItemListsContainer ul:eq(0)', $(data))[0].outerHTML;
plist = $('div.pagination div.wrapper:eq(0)', $(data))[0].outerHTML;
//div = '<div class="pre-reading" id="pre-id-' + tmp[0] + '">' + content + '</div>';
$content = $(content).attr('id', 'ul-page-' + tmp[0]).addClass('pre-reading');
$body.append($content); // 预读图片资源
pageCache[tmp[0]] = {"list": $(content), "pageList": $(plist), "page": tmp[0]};
$('#' + tmp[2]).addClass('save-flag'); //修改当前页码为绿色(已缓存
})
})(tmp);
}
s.DATA.config.act_type == 0 && setTimeout(function() {
$('ul.pre-reading').remove();
}, 8000); // 8秒后移除
}
},
/* 翻页操作 */
pageTurning: function(_cmd) {
var s = this, pageData = s.DATA.pageData, act_type = s.DATA.config.act_type;
pageDataDeal(_cmd);
// 页码数据 替换 商品列表ul + 页码列表div
var curr = pageData.pageCurr;
var pageCache = pageData.pagePreReadingData;
if (typeof pageCache[curr] == 'undefined') {
alert('页码[' + curr + ']尚未缓存成功,请稍后再试');
return false;
}
var pageInfo = pageCache[curr];
$('div.pagination div.wrapper:eq(0)').remove();
$('div.pagination').append(pageInfo.pageList);
s.preReading(); // 继续预读当前未缓存的页码
if (act_type == 0) {
$('#J_ItemListsContainer ul:eq(0)').remove();
$('#J_ItemListsContainer').append(pageInfo.list);
$('html, body').animate({scrollTop: $('#J_ItemListsContainer').offset().top}, s.DATA.config.scroll_time); // 描点回到顶部
} else if (act_type == 1) {
var uid = '#ul-page-' + pageInfo.page;
$('#J_ItemListsContainer').append($(uid).removeClass('pre-reading'));
$('html, body').animate({scrollTop: $(uid).offset().top}, s.DATA.config.scroll_time);
}
// 页码信息处理
function pageDataDeal(_cmd) {
_cmd = _cmd || 'next'; // 默认下一页
var cmd_arr = ['next', 'pre', '下一页', '上一页'];
var cmd, cmd_n = parseInt(_cmd);
if (cmd_n >= 1) { // 按指定数字页码翻页
if (cmd_n == pageData.pageCurr) { // 当前页 不处理
console.log('log: pageNum == pageCurr !');
return false;
}
cmd = cmd_n < pageData.pageTotal ? cmd_n : pageData.pageTotal;
pageData.pageCurr = cmd;
pageData.pageNext = cmd >= pageData.pageTotal ? null : cmd + 1;
pageData.pagePre = cmd <= 1 ? null : cmd - 1;
} else {
cmd = $.inArray(_cmd, cmd_arr) == -1 ? false : _cmd;
if (cmd == false) {
console.log('log: cmd[' + _cmd + '] was not accepted !');
return false; // 指令有误
}
if (cmd == 'next' || cmd == '下一页') {
if (pageData.pageNext == null) {
console.log('log: No pageNext !');
return false;
}
++pageData.pagePre;
++pageData.pageCurr;
var next = pageData.pageNext + 1;
pageData.pageNext = next > pageData.pageTotal ? null : next;
} else if (cmd == 'pre' || cmd == '上一页') {
if (pageData.pagePre == null) {
console.log('log: No pagePre !');
return false;
}
--pageData.pageNext;
--pageData.pageCurr;
var pre = pageData.pagePre - 1;
pageData.pagePre = pre < 1 ? null : pre;
}
}
}
},
/* 数据操作 */
dataMgr: function (act) {
var s = this;
var action = act == 'set' ? 'set' : 'get';
if (action == 'get') {
var cfgStr = GM_getValue('config');
if (typeof cfgStr == 'undefined' || cfgStr == '') {
s.DATA.config = s.DATA.defaultCfg;
return true;
}
var cfg_obj = JSON.parse(cfgStr);
$.extend(s.DATA.config, s.DATA.defaultCfg, cfg_obj); // 合并
} else {
var cfgStr = JSON.stringify(s.DATA.config);
GM_setValue('config', cfgStr);
}
},
/* 双击判定 */
doubleClick: function (keyCode) {
var s = this;
var timenow = (new Date()).getTime();
if (s.DATA.keyData.timenow == 0) {
s.DATA.keyData.timenow = timenow;
s.DATA.keyData.preKey = keyCode;
return false;
} else {
var intval = timenow - s.DATA.keyData.timenow;
if (intval < s.DATA.keyData.keepTime && s.DATA.keyData.preKey == keyCode) {
s.DATA.keyData.timenow = 0;
return true;
}
s.DATA.keyData.preKey = keyCode;
s.DATA.keyData.timenow = timenow;
}
return false;
}
};
AliObj.launcher(config);
/* 工具函数 */
// 仿PHP 正则
function preg_match_all(match, str, _type) {
// _type: [A] 默认排序 同序号/顺序的所有匹配结果放入同一数组; [B] 一次匹配的所有结果放入同一个数组
var type = typeof _type != 'undefined' && _type == 'B' ? 'B' : 'A';
var cat, data = [];
while ((cat = match.exec(str)) != null) {
data.push(cat);
}
if (data.length == 0) return false; // 无匹配
// A模式排序 处理
if (type == 'A') {
var dataTmp = [], tmp;
for (var i in data) {
tmp = data[i];
for (var ii in tmp) {
if (typeof dataTmp[ii] == 'undefined') dataTmp[ii] = [];
dataTmp[ii].push(tmp[ii]);
}
}
data = dataTmp;
}
return data;
}