Greasy Fork is available in English.

Xianyu Page Turning By AJAX

闲鱼: 搜索列表改无刷新(预读)翻页:双击【←→】键快速翻页

От 28.12.2016. Виж последната версия.

// ==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;
}