Greasy Fork

Greasy Fork is available in English.

京东自营过滤

在京东商品列表和搜索结果页面增加【自营】【非自营】以及【满赠】【满减】等超过30个商品过滤选项,为【京东配送】【仅显示有货】以及【排序】选项增加记忆功能。

当前为 2020-04-25 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         京东自营过滤
// @version      0.5.3.1
// @icon         https://www.jd.com/favicon.ico
// @description  在京东商品列表和搜索结果页面增加【自营】【非自营】以及【满赠】【满减】等超过30个商品过滤选项,为【京东配送】【仅显示有货】以及【排序】选项增加记忆功能。
// @author       You!
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @grant        GM_addStyle
// @grant        unsafeWindow
// @include      *://list.jd.com/list.html?*
// @include      *://coll.jd.com/list.html?*
// @include      *://list.jd.com/search?*
// @include      *://list.jd.com/Search?*
// @include      *://search.jd.com/search?*
// @include      *://search.jd.com/Search?*
// @include      *://www.jd.com/pinpai/*
// @require      https://code.jquery.com/jquery-3.3.1.min.js
// @require      https://code.jquery.com/color/jquery.color-2.1.2.min.js
// @run-at       document-start
// @namespace    http://greasyfork.icu/zh-CN/scripts/33729-京东自营过滤
// ==/UserScript==

(function() {
	'use strict';

	//过滤器
	var jdGoodsFilters = [
		//自营,非自营
		{name:'自营',nameN:'非自营',lv:0,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'京东自营,品质保障'
			]}
		]},

		//PLUS会员价
		{name:'PLUS会员',nameN:'非PLUS会员',lv:1,conditions:[
			{type:'attr',tag:'span',attr:'title',vals:[
				'PLUS会员专享价'
			]}
		]},

		//优惠券
		{name:'优惠券',nameN:'无优惠券',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'优惠券',
				'本商品可领用优惠券'
			]}
		]},

		//满减
		{name:'满减',nameN:'非满减',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'该商品参加满减活动',
				'本商品参与满减促销',
				'满减'
			]},
		]},

		//满件
		{name:'满件',nameN:'非满件',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'本商品参与满件促销'
			]}
		]},

		//满赠
		{name:'满赠',nameN:'非满赠',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'该商品参加满赠活动'
			]}
		]},

		//赠品
		{name:'赠品',nameN:'无赠品',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'购买本商品送赠品'
			]}
		]},

		//京东物流
		{name:'京东物流',nameN:'非京东物流',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'京东物流仓配,商家提供售后服务'
			]}
		]},

		//厂商配送
		{name:'厂商配送',nameN:'非厂商配送',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'厂家或供应商发货和配送'
			]}
		]},

		//到店自取
		{name:'到店自取',nameN:'非到店自取',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'该商品支持到店自取'
			]}
		]},

		//免邮
		{name:'免邮',nameN:'不免邮',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'当前收货地址,该商品免邮费',
				'当前收货地址,本商品免邮费'
			]}
		]},

		//运费险
		{name:'运费险',nameN:'无运费险',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'运费险',
				'退换货免运费'
			]},
		]},

		//京尊达
		{name:'京尊达',nameN:'非京尊达',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'专人配送,尊贵体验'
			]}
		]},

		//预约抢购
		{name:'预约抢购',nameN:'非预约抢购',conditions:[
			{type:'multi',vals:[
				{tag:'div',cls:'p-presell-time',textAny:['预约']},
			]},
		]},

		//秒杀
		{name:'秒杀',nameN:'非秒杀',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'天天低价,正品保证'
			]}
		]},

		//闪购
		{name:'闪购',nameN:'非闪购',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'品牌限时特卖'
			]}
		]},

		//定期购
		{name:'定期购',nameN:'非定期购',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'定期免运费,省心又优惠'
			]}
		]},

		//全球购
		{name:'全球购',nameN:'非全球购',conditions:[
			{type:'text',tag:'span',vals:[
				'全球购'
			]}
		]},

		//包税
		{name:'包税',nameN:'不包税',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'本商品已包税'
			]}
		]},

		//新品
		{name:'新品',nameN:'非新品',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'该商品是当季新品'
			]}
		]},

		//商场同款
		{name:'商场同款',nameN:'非商场同款',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'该商品是商场同款'
			]}
		]},

		//京东精选
		{name:'京东精选',nameN:'非京东精选',lv:1,conditions:[
			{type:'attr',tag:'img',attr:'src',vals:[
				'//img14.360buyimg.com/uba/jfs/t6919/268/501386350/1257/92e5fb39/5976fcf9Nd915775f.png'
			]},
			{type:'attr',tag:'img',attr:'data-tips',vals:[
				'京东精选'
			]}
		]},

		//品质优选
		{name:'品质优选',nameN:'非品质优选',lv:1,conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'只为品质生活'
			]}
		]},

		//京东超市
		{name:'京东超市',nameN:'非京东超市',lv:1,conditions:[
			{type:'text',tag:'span',vals:[
				'京东超市'
			]}
		]},

		//Sam's
		{name:'山姆会员',nameN:'非山姆会员',lv:1,conditions:[
			{type:'shop',vals:[
				'山姆会员商店官方旗舰店',
				'山姆会员商店全球购官方旗舰店'
			]},
			{type:'multi',vals:[
				{tag:'span',cls:'price-sams-1'},
				{tag:'em',textStart:'¥'}
			]},
		]},

		//有机
		{name:'有机',nameN:'非有机',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'有机'
			]}
		]},

		//绿色
		{name:'绿色',nameN:'非绿色',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'绿色'
			]}
		]},

		//无公害
		{name:'无公害',nameN:'非无公害',conditions:[
			{type:'text',tag:'i',vals:[
				'无公害'
			]}
		]},

		//三同
		{name:'三同',nameN:'非三同',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'三同'
			]}
		]},

		//京东检测
		{name:'京东检测',nameN:'非京东检测',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'京东检测'
			]}
		]},

		//双11保价
		{name:'双11保价',nameN:'无双11保价',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'商品当前价格已与11.11当天一致,买贵返还差额'
			]}
		]},

		//老字号
		{name:'老字号',nameN:'非老字号',conditions:[
			{type:'text',tag:'i',vals:[
				'老字号'
			]}
		]},

		//地标产品
		{name:'地标产品',nameN:'非地标产品',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'地标产品'
			]}
		]},

		//ASC
		{name:'ASC',nameN:'非ASC',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'ASC'
			]}
		]},

		//BAP
		{name:'BAP',nameN:'非BAP',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'BAP'
			]}
		]},

		//海产品捕捞认证
		{name:'海捕证',nameN:'无海捕证',conditions:[
			{type:'text',tag:'i',vals:[
				'海产品捕捞认证'
			]}
		]},

		//商家客服
		{name:'商家客服',nameN:'无商家客服',lv:1,conditions:[
			{type:'attr',tag:'b',attr:'title',vals:[
				'联系客服'
			]},
			{type:'attr',tag:'em',attr:'title',vals:[
				'联系供应商进行咨询',
				'联系第三方卖家进行咨询',
				'供应商客服不在线,可留言'
			]}
		]},

		//抢购中
		{name:'抢购中',nameN:'非抢购中',conditions:[
			{type:'multi',vals:[
				{tag:'div',cls:'p-presell-time'},
				{tag:'span',textAny:['抢购中']}
			]}
		]},

		//有货
		{name:'有货',nameN:'无货',conditions:[
			{type:'multi',not:true,vals:[
				{tag:'div',cls:'p-stock',textAny:['无货']}
			]}
		]},

		//预订
		{name:'预订',nameN:'非预订',conditions:[
			{type:'multi',vals:[
				{tag:'div',cls:'p-stock',textAny:['预订']}
			]}
		]},

		//配送
		{name:'支持配送',nameN:'不支持配送',conditions:[
			{type:'multi',not:true,vals:[
				{tag:'div',cls:'p-stock',textAny:['不支持配送']}
			]}
		]},

		//二手有售
		{name:'二手有售',nameN:'非二手有售',conditions:[
			{type:'multi',vals:[
				{tag:'a',cls:'spu-link',texts:['二手有售']}
			]}
		]},

		//二手
		{name:'二手',nameN:'非二手',conditions:[
			{type:'multi',vals:[
				{tag:'span',cls:'p-tag',texts:['拍拍']}
			]}
		]},

		//2人拼
		{name:'2人拼',nameN:'非2人拼',conditions:[
			{type:'text',tag:'span',vals:[
				'2人拼'
			]}
		]},

		//放心购
		{name:'放心购',nameN:'非放心购',conditions:[
			{type:'text',tag:'i',vals:[
				'放心购'
			]}
		]},

		//爱心东东
		{name:'爱心东东',nameN:'非爱心东东',conditions:[
			{type:'text',tag:'span',vals:[
				'爱心东东'
			]}
		]},

		//广告
		{name:'广告',nameN:'非广告',conditions:[
			{type:'text',tag:'span',vals:[
				'广告'
			]}
		]},

		//本地仓(据说已经废弃?)
		{name:'本地仓',nameN:'非本地仓',conditions:[
			{type:'attr',tag:'i',attr:'data-tips',vals:[
				'从您所在城市的京东仓库发货,当日上午11:00前提交的现货订单,当日送达;当日23:00前提交的现货订单,次日15:00前送达'
			]}
		]},

		//商品名匹配
		{name:'商品名匹配',nameN:'商品名不匹配',conditions:[
			{type:'multi',vals:[
				{tag:'div',cls:'p-name'},
				{tag:'em'}
			]}],
			_hlInfo:{ //私有数据
				tag: 'b',
				cls: 'hl',
				getEmTag: function(elem) {
					return elem.emTag || (elem.emTag = elem.getElementsByClassName('p-name')[0].getElementsByTagName('em')[0]);
				}
			},
			onPassed: function(elem) { //过滤器命中时执行:先取消高亮,再重新高亮
				if (!unsafeWindow.x$.highlightGoodsPattern) return this.onMissed(elem);
				var hlInfo = this._hlInfo;
				var em = hlInfo.getEmTag(elem);
				var condVal = this.conditions[0].vals[1];
				var match = condVal.textAny || condVal.textAll || condVal.textRex;
				if (!match) return this.onMissed(elem);
				var hlMatch = elem.highlighted;
				var html = em.innerHTML;
				var hlHtml = hlMatch === undefined ?
					highlightHtml(html, match, hlInfo) : //新加高亮
					replaceHighlightHtml(html, match, hlMatch, hlInfo); //已经高亮过,尝试替换
				if (hlHtml !== null) {
					elem.highlighted = match;
					em.innerHTML = hlHtml;
				}
			},
			onMissed: function(elem) { //过滤器未命中时执行:取消高亮
				if (!elem.highlighted) return;
				var hlInfo = this._hlInfo;
				var em = hlInfo.getEmTag(elem);
				var html = unhighlightHtml(em.innerHTML, hlInfo);
				if (html) em.innerHTML = html;
				delete elem.highlighted;
			},
			init: function() { //过滤器初始化,只运行一次
				var hlInfo = this._hlInfo;
				hlInfo.tag0 = [];
				for(var i=1; i<=9; ++i) hlInfo.tag0.push('<'+hlInfo.tag+' class="'+hlInfo.cls+i+'">');
				hlInfo.tag1 = '</'+hlInfo.tag+'>';
			}
		}
	];
	//过滤器处理程序
	var goodsFilterMap = {
		attr: function(elem, cond) {
			var tags = elem.getElementsByTagName(cond.tag);
			for (var i=0; i<tags.length; ++i) {
				var attr = tags[i].getAttribute(cond.attr);
				if (attr !== null && includesAny(attr, cond.vals)) return true;
			}
			return false;
		},
		text: function(elem, cond) {
			var tags = elem.getElementsByTagName(cond.tag);
			for (var i=0; i<tags.length; ++i) {
				var text = tags[i].innerText;
				if (text.length > 0 && (text = text.trim()).length > 0 && includesAny(text, cond.vals)) return true;
			}
			return false;
		},
		multi: function(elem, cond) {
			return filterTag(elem, cond.vals, 0);
			function filterTag(elem, conds, ci) {
				var cond = conds[ci];
				var tags = elem.getElementsByTagName(cond.tag);
				for (var i = 0; i < tags.length; ++i) {
					var tag = tags[i];
					if (cond.cls && !hasClasses(tag, cond.cls)) continue;
					//if (cond.attr && !hitAttributes(tag, cond.attr)) continue;
					var text = tag.innerText.trim();
					if (cond.texts && (text.length === 0 || !isAny(text, cond.texts))) continue;
					if (cond.textAny && (text.length === 0 || !includesAny(text, cond.textAny))) continue;
					if (cond.textAll && (text.length === 0 || !includesAll(text, cond.textAll))) continue;
					if (cond.textStart && (text.length === 0 || !text.startsWith(cond.textStart))) continue;
					// if (cond.textEnd && (text.length === 0 || !text.endsWith(cond.textEnd))) continue;
					// if (cond.textSub && (text.length === 0 || !text.includes(cond.textSub))) continue;
					if (cond.textRex && (text.length === 0 || (cond.textRex.lastIndex = 0) || !cond.textRex.test(text))) continue;
					return (++ci === conds.length) || filterTag(tag, conds, ci);
				}
				return false;
				function hasClasses(e,c) {
					if (!(c instanceof Array)) return e.classList.contains(c);
					for (var i=0; i<c.length; ++i) if (!e.classList.contains(c[i])) return false;
					return true;
				}
				// function hitAttributes(e,c) {
				// 	if (!(c instanceof Array)) return hitAttribute(e, c);
				// 	for (var i=0; i<c.length; ++i) if (!hitAttribute(e, c[i])) return false;
				// 	return true;
				// 	function hitAttribute(e,c) {
				// 		var a = e.getAttribute(c.attr);
				// 		return a !== null && includesAny(a, c.vals);
				// 	}
				// }
			}
		},
		shop: function(elem, cond) {
			var tags = elem.getElementsByTagName('div');
			for (var i=0; i<tags.length; ++i) {
				var tag = tags[i];
				if (tag.classList.contains('p-shop')) {
					var tags2 = tag.getElementsByTagName('a');
					for (var j=0; j<tags2.length; ++j) {
						var title = tags2[j].title;
						if (title.length > 0 && (title = title.trim()).length > 0 && cond.vals.includes(title)) return true;
					}
				}
			}
			return false;
		}//,
		// fn: function(elem, cond) {
		// 	for (var i=0; i<cond.vals.length; ++i) {
		// 		if (cond.vals[i](elem, cond)) return true;
		// 	}
		// 	return false;
		// }
	};

	//防止页面重入
	if (document.getElementById('goodsFilter'+jdGoodsFilters[0].name) !== null) return;

	//扫描页面的间隔频率时间
	var timerFreq = 333;
	//当前页面路径
	var currentPathname = location.pathname.toLowerCase();
	if (currentPathname.startsWith('/pinpai/')) currentPathname = '/search';
	//京东自带过滤器和排序选项
	var jdFilters = {
		京东配送: {type:0, gm_name:'京东配送', val:'1'},
		货到付款: {type:0, gm_name:'货到付款', val:'1'},
		仅显示有货: {type:0, gm_name:'仅显示有货', name:'stock',val:'1',def:'0'},
		排序: {type:1, gm_name:'排序', vals:[
			//综合没有值
			'sort_dredisprice_desc',
			'sort_dredisprice_asc',
			'sort_totalsales15_desc',
			'sort_commentcount_desc',
			'sort_winsdate_desc'
		]}
	};
	//检查插件数据
	CheckSettings(true);
	//通过重定向应用保存的京东自带过滤器和排序选项
	var newSearch = OnDocStart();
	if (newSearch !== undefined) location.search = newSearch;
	else setTimeout(OnDocReady, 0);

	//载入【京东配送】【仅显示有货】和排序的设置,返回重定向的路径
	function OnDocStart() {
		switch (currentPathname) {
			case '/search':
				jdFilters.京东配送.name = 'wtype';
				jdFilters.货到付款.name = 'cod';
				jdFilters.排序.name = 'psort';
				break;

			case '/list.html':
				jdFilters.京东配送.name = 'delivery';
				jdFilters.货到付款.name = 'delivery_daofu';
				jdFilters.货到付款.val = '3';
				jdFilters.排序.name = 'sort';
				break;
		}
		var urlOpts = url2Obj();
		if (readOpts(urlOpts)) {
			var newSearch = '?';
			for (var opt in urlOpts) {
				if (newSearch.length > 1) newSearch += '&';
				newSearch += opt;
				newSearch += '=';
				newSearch += urlOpts[opt];
			}
			return newSearch.length > 1 ? newSearch : '';
		}

		function url2Obj() {
			var ret = {};
			var u = location.search.split(/[\?&]/);
			for (var i in u) {
				var opt = u[i];
				if (opt.length > 0) {
					opt = opt.split('=');
					ret[opt[0]] = opt[1];
				}
			}
			return ret;
		}
		function readOpts(opts) {
			var modified;
			for (var optKey in jdFilters) {
				var opt = jdFilters[optKey];
				switch (opt.type) {
					case 0: modified |= readFilterOpt(opts, opt); break;
					case 1: modified |= readSortOpt(opts, opt); break;
				}
			}
			return modified;

			function readFilterOpt(opts, opt) {
				if (GM_getValue(opt.gm_name)) { //有保存的值
					if (!opts.hasOwnProperty(opt.name) || opts[opt.name] !== opt.val) {
						opts[opt.name] = opt.val;
						return true;
					}
				} else { //没有保存的值
					if (opt.def !== undefined) { //不允许url不带该参数
						if (opts.hasOwnProperty(opt.name)) {
							if (opts[opt.name] !== opt.def) {
								opts[opt.name] = opt.def;
								return true;
							}
						} else {
							opts[opt.name] = opt.def;
							return true;
						}
					} else if (opts.hasOwnProperty(opt.name) && opts[opt.name] !== '0') {
						delete opts[opt.name];
						return true;
					}
				}
				return false;
			}
			function readSortOpt(opts, opt) {
				var sortOpt = GM_getValue(opt.gm_name);
				switch (currentPathname) {
					case '/search':
						if (sortOpt !== undefined) ++sortOpt;
						break;

					case '/list.html':
						sortOpt = jdFilters.排序.vals[sortOpt];
						break;
				}

				if (sortOpt !== undefined) {
					if (!opts.hasOwnProperty(opt.name) || urlOpts[opt.name] != sortOpt) {
						urlOpts[opt.name] = sortOpt;
						return true;
					}
				} else if (opts.hasOwnProperty(opt.name)) {
					delete opts[opt.name];
					return true;
				}
				return false;
			}
		}
	}
	//载入页面后,为页面增加【自营】【非自营】等过滤器
	function OnDocReady() {
		//防止页面重入
		if (document.getElementById('goodsFilter'+jdGoodsFilters[0].name) !== null) return;

		runMain();

		//页面入口点
		function runMain() {
			if ($ && $.fn && $.fn.jquery) {
				enableAllFilters();
				loadAllSettings();
				initAllFilters();
				uiInitAndLoadAllGoods();
			} else setTimeout(runMain, timerFreq);

			function enableAllFilters() {
				for (var i=0; i<jdGoodsFilters.length; ++i) if (jdGoodsFilters[i].lv === undefined) jdGoodsFilters[i].lv = 1;
			}
			//加载设置
			function loadAllSettings() {
				unsafeWindow.x$ = { //init:设置数据缓冲
					infoLogText: '正在等待商品列表加载,请稍候……'
				};
				unsafeWindow.y$ = {}; //init:设置控件引用缓冲
				unsafeWindow.z$ = {}; //init:设置临时缓冲

				loadAllFiltersStates(); //加载过滤器选中状态
				loadFilterMode(); //加载过滤方式
				loadMisc(); //加载其他设置

				function loadAllFiltersStates() {
					for (var i=0; i<jdGoodsFilters.length; ++i) {
						var f = jdGoodsFilters[i];
						//加载启用状态
						f.level = GM_getValue('level'+f.name);
						if (f.level === undefined && f.lv !== undefined) f.level = f.lv;
						//加载选中状态
						f.checked = undefined === GM_getValue(f.name);
						f.checkedN = undefined === GM_getValue(f.nameN);
					}
					//【商品名匹配使用正则】设置
					var useRegex = GM_getValue('商品名匹配正则');
					if (useRegex !== undefined) unsafeWindow.x$.useRegexChecked = true; //init:商品名匹配正则
					//【商品名匹配高亮】设置
					if (GM_getValue('商品名匹配不高亮') === undefined) unsafeWindow.x$.highlightGoodsPattern = true; //init:商品名匹配高亮

					//【商品名匹配】过滤器
					var cond = jdGoodsFilters[jdGoodsFilters.findIndex(function(j) {return j.name === '商品名匹配';})].conditions[0].vals[1];
					var pattern = GM_getValue('商品名匹配规则');
					if (pattern !== undefined) {
						unsafeWindow.x$.goodsPattern = pattern;
						if (useRegex) cond.textRex = ToRegex(pattern);
						else {
							var txtCond = ToTextCond(pattern);
							if (txtCond.allMatch) cond.textAll = txtCond.txts;
							else cond.textAny = txtCond.txts;
						}
					}
					unsafeWindow.x$.goodsPatternCondition = cond; //init:商品名匹配规则
				}
				function loadFilterMode() {
					unsafeWindow.x$.filterModes = [ //init:设置过滤方式字典
						'akari',
						'haruhi',
						'cirno',
						'yuno',
						'mizuki',
						'burnIt',
						'succubus',
						'conan',
						'hphphp'
					];
					unsafeWindow.x$.goodsFilterModeIndex = GM_getValue('过滤方式'); //init:过滤方式索引
					if (unsafeWindow.x$.goodsFilterModeIndex === undefined) unsafeWindow.x$.goodsFilterModeIndex = 0; //init:过滤方式索引没有保存
					else if (unsafeWindow.x$.goodsFilterModeIndex < 0 || unsafeWindow.x$.goodsFilterModeIndex >= unsafeWindow.x$.filterModes.length) unsafeWindow.x$.goodsFilterModeIndex = 0; //init:过滤方式索引超限
					unsafeWindow.x$.goodsFilterModeClass = unsafeWindow.x$.filterModes[unsafeWindow.x$.goodsFilterModeIndex]; //init:过滤方式的className

					if (GM_getValue('后排') !== undefined) unsafeWindow.x$.filteredToLastChecked = true; //init:后排设置
				}
				function loadMisc() {
					if (GM_getValue('老爷机不要动画') !== undefined) unsafeWindow.x$.noAnimateChecked = true; //init:关闭动画设置
				}
			}
			//初始化过滤器
			function initAllFilters() {
				for (var i=0; i<jdGoodsFilters.length; ++i) {
					var f = jdGoodsFilters[i];
					if (f.init !== undefined) f.init();
				}
			}
		}
		//向页面添加自营过滤选项
		function uiInitAndLoadAllGoods() {
			var uiPos = $(document.querySelector('.f-feature ul'));
			if (uiPos.length > 0) {
				//改造京东自身过滤器和排序按钮
				hookJdFilters();
				//向页面添加过滤器
				addFiltersParts();
				//分页面情况处理后续是否加载商品
				switch (currentPathname) {
					case '/search':
						if (document.querySelector('div.notice-filter-noresult') !== null) { //搜索没有结果
							updateInfoLog('');
							return;
						}
				}
				//UI 初始化成功,加载所有商品
				loadAllGoods();
			} else setTimeout(uiInitAndLoadAllGoods, timerFreq);

			function hookJdFilters() {
				switch (currentPathname) {
					case '/search':
						//【京东配送】【货到付款】【仅显示有货】【全球配送】【节日促销】按钮重载 searchlog
						uiPos.find('li a[onclick]').each(function() {
							var tagA = $(this);
							if (tagA.attr('onclick').length > 0) this.oldOnClick = this.onclick;
							tagA.removeAttr('onclick');
							tagA.click(function() {
								if (this.oldOnClick !== undefined) {
									this.oldOnClick();
									var waitAjaxLoadGoodsList = function() {
										if (unsafeWindow.SEARCH.loading) setTimeout(waitAjaxLoadGoodsList, timerFreq);
										else runMain();
									};
									setTimeout(waitAjaxLoadGoodsList, timerFreq);
								}
							});
						});

						//【综合】【销量】【评论】【新品】【价格】排序按钮重载
						hookSearchSortHtml();
						//翻页按钮重载
						hookPager();
						//重载搜索排序函数,保存排序选项
						hookSearchSort();

						//【京东配送】【货到付款】【仅显示有货】按钮
						jdFilters.京东配送.aTag = uiPos.find('li a[data-field="wtype"]').first();
						jdFilters.货到付款.aTag = uiPos.find('li a[data-field="cod"]').first();
						jdFilters.仅显示有货.aTag = uiPos.find('li a[data-field="stock"]').first();
						break;

					case '/list.html':
						//【综合】【销量】【价格】【评论】【上架】排序按钮重载,保存排序设置
						$(document.querySelectorAll('#J_filter div.f-sort a:not([id])')).click(function() {
							var aTagSort = $(this);
							setTimeout(function() {
								var sortOpt = aTagSort.attr('href').match(/[&\?]sort=([^&]*)/i);
								if (sortOpt && 2 === sortOpt.length) {
									sortOpt = unescape(sortOpt[1]);
									for (var i=0; i<jdFilters.排序.vals.length; ++i) {
										if (sortOpt === jdFilters.排序.vals[i]) {
											GM_setValue(jdFilters.排序.gm_name, i);
											break;
										}
									}
								} else GM_deleteValue(jdFilters.排序.gm_name);
							}, 0);
						});

						//【京东配送】【货到付款】【仅显示有货】按钮
						switch (location.host) {
							case 'list.jd.com':
								jdFilters.京东配送.aTag = uiPos.find('li#delivery a').first();
								jdFilters.货到付款.aTag = uiPos.find('li#delivery_daofu a').first();
								jdFilters.仅显示有货.aTag = uiPos.find('li#stock a').first();
								break;

							case 'coll.jd.com':
								jdFilters.京东配送.aTag = uiPos.find('li a:contains(京东配送)').first();
								jdFilters.货到付款.aTag = uiPos.find('li a:contains(货到付款)').first();
								jdFilters.仅显示有货.aTag = uiPos.find('li a:contains(仅显示有货)').first();
								break;
						}
						break;
				}
				//【京东配送】按钮保存设置
				jdFilters.京东配送.aTag.click(function() {
					setTimeout(function() {
						if (jdFilters.京东配送.aTag.hasClass('selected') ^ (currentPathname === '/search')) GM_deleteValue(jdFilters.京东配送.gm_name);
						else GM_setValue(jdFilters.京东配送.gm_name, true);
					}, 0);
				});
				//【货到付款】按钮保存设置
				jdFilters.货到付款.aTag.click(function() {
					setTimeout(function() {
						if (jdFilters.货到付款.aTag.hasClass('selected') ^ (currentPathname === '/search')) GM_deleteValue(jdFilters.货到付款.gm_name);
						else GM_setValue(jdFilters.货到付款.gm_name, true);
					}, 0);
				});
				//【仅显示有货】按钮保存设置
				jdFilters.仅显示有货.aTag.click(function() {
					setTimeout(function() {
						if (jdFilters.仅显示有货.aTag.hasClass('selected') ^ (currentPathname === '/search')) GM_deleteValue(jdFilters.仅显示有货.gm_name);
						else GM_setValue(jdFilters.仅显示有货.gm_name, true);
					}, 0);
				});

				function hookSearchSortHtml() {
					if (unsafeWindow.SEARCH !== undefined && unsafeWindow.SEARCH.sort_html !== undefined) {
						if (unsafeWindow.SEARCH.oldFunc_sort_html === undefined) {
							unsafeWindow.SEARCH.oldFunc_sort_html = unsafeWindow.SEARCH.sort_html;
							unsafeWindow.SEARCH.sort_html = function(C) { //重载 SEARCH.sort_html 函数
								unsafeWindow.SEARCH.oldFunc_sort_html(C);
								//在 loadAllGoods 处理 /search 页面的分支中会调用 SEARCH.scroll 来加载商品列表后半页,
								//这会导致 SEARCH.sort_html 被再次调用,如果在重载的函数中再次【直接】【自动】调用 loadAllGoods 会构成递归溢出,
								//因此必须将 loadAllGoods 的调用放在排序按钮的 onclick 事件响应里面,并删除原始的 onclick 属性内联调用
								$(document.querySelectorAll('#J_filter div.f-sort a[onclick]')).each(function() {
									var tagA = $(this);
									if (tagA.attr('onclick').length > 0) this.oldOnClick = this.onclick;
									tagA.removeAttr('onclick');
									tagA.click(function() {
										if (this.oldOnClick !== undefined) {
											this.oldOnClick();
											var waitAjaxLoadGoodsList = function() {
												if (unsafeWindow.SEARCH.loading) setTimeout(waitAjaxLoadGoodsList, timerFreq);
												else loadAllGoods();
											};
											setTimeout(waitAjaxLoadGoodsList, timerFreq);
										}
									});
								});
							};
						}
					} else setTimeout(hookSearchSortHtml, timerFreq);
				}
				function hookPager() {
					if (undefined !== unsafeWindow.SEARCH && undefined !== unsafeWindow.SEARCH.page) {
						if (unsafeWindow.SEARCH.oldFunc_page === undefined) {
							unsafeWindow.SEARCH.oldFunc_page = unsafeWindow.SEARCH.page;
							unsafeWindow.SEARCH.page = function(F, C) { //重载 SEARCH.page 函数
								unsafeWindow.SEARCH.oldFunc_page(F, C);
								//loadAllGoods 不会与 SEARCH.page 发生嵌套循环调用,所以可以在重载函数内直接调用 loadAllGoods
								var waitAjaxLoadGoodsList = function() {
									if (unsafeWindow.SEARCH.loading) setTimeout(waitAjaxLoadGoodsList, timerFreq);
									else loadAllGoods();
								};
								setTimeout(waitAjaxLoadGoodsList, timerFreq);
							};
						}
					} else setTimeout(hookPager, timerFreq);
				}
				function hookSearchSort() {
					if (unsafeWindow.SEARCH !== undefined && unsafeWindow.SEARCH.sort !== undefined) {
						if (unsafeWindow.SEARCH.oldFunc_sort === undefined) {
							unsafeWindow.SEARCH.oldFunc_sort = unsafeWindow.SEARCH.sort;
							unsafeWindow.SEARCH.sort = function(A) { //重载 SEARCH.sort 函数
								unsafeWindow.SEARCH.oldFunc_sort(A);
								setTimeout(function() {
									if (!A) GM_deleteValue(jdFilters.排序.gm_name); else GM_setValue(jdFilters.排序.gm_name, A-1);
								}, 0);
							};
						}
					} else setTimeout(hookSearchSort, timerFreq);
				}
			}
			function addFiltersParts() {
				//向页面添加样式表
				if (document.getElementById('styleGoodsFilters') === null) GM_addStyle(
					//计数器占位符和计数器样式
					'span.goodsCountPlaceholder{width:36px;display:inline-block;}'+
					'span.goodsCount{font-size:10px;color:#fff;background-color:#e23a3a;border-radius:3px;padding:0px 3px;}'+
					//顶级过滤器样式
					'div.f-feature>ul>li>a>span.goodsCount{margin-left:2px;}'+
					//过滤器样式(必须带【.filter .f-feature ul li】前置,否则会被京东自身样式覆盖)
					'.filter .f-feature ul li a{padding-right:8px;}'+
					'.filter .f-feature ul li a.filterN{color:#888;}'+
					'.filter .f-feature ul li a.filterN:hover{color:#e23a3a;}'+
					'.filter .f-feature ul li a.filterN.selected i{border-color:rgba(228,57,60,0.3);}'+
					'.filter .f-feature ul li a.filterN.selected:hover i{border-color:#e4393c;}'+
					'.filter .f-feature ul li a.zeroCountGoods{color:#ccc;}'+
					'.filter .f-feature ul li a.zeroCountGoods.selected i{border-color:#ccc;}'+
					'.filter .f-feature ul li a.zeroCountGoods span.goodsCount{background-color:#ccc;}'+
					'.filter .f-feature ul li a.zeroCountGoods:hover{color:#e23a3a;}'+
					'.filter .f-feature ul li a.zeroCountGoods.selected:hover i{border-color:#e4393c;}'+
					//【下级过滤器】按钮
					'.filter .f-feature ul li.showMoreFilters{padding-right:12px;}'+
					'.filter .f-feature ul li.showMoreFilters a{padding:0 2px;color:#e23a3a;line-height:normal;border:1px solid #e23a3a;border-radius:3px;}'+
					'.filter .f-feature ul li.showMoreFilters a.opened{color:white;background:#e23a3a;}'+
					//过滤器数量蓝点
					'.filter .f-feature ul li.showMoreFilters a #moreFiltersCount{color:white;background:dodgerblue;position:absolute;top:-4px;right:-10px;width:16px;height:16px;line-height:15px;border-radius:8px;font-size:8px;text-align:center;user-select:none;cursor:pointer;}'+
					//过滤器面板
					'#moreFiltersPanel{border:1px solid #E7E3E7;z-index:0;}'+
					'#moreFiltersPanel *{white-space:nowrap;}'+
					//过滤器表格和动作条分割线
					'#moreFiltersPanel hr{margin:0 5px;border:0;border-top:1px solid #E7E3E7;}'+
					//过滤器面板div布局
					'#moreFiltersPanel div{display:flex;justify-content:center;align-items:center;}'+
					//过滤器表格样式
					'table.f-feature{margin:3px 0;border-collapse:collapse;}'+
					'table.f-feature td{padding:0 5px;text-align:center;}'+
					//过滤器组分割线
					'table.f-feature td:nth-child(3n+4){border-left:1px solid #E7E3E7;}'+
					//左侧过滤器样式
					'table.f-feature td:nth-child(3n+1){text-align:right;}'+
					'table.f-feature td:nth-child(3n+1) ul li a{padding:0;}'+
					'table.f-feature td:nth-child(3n+1) ul li a i{margin:0 0 0 4px;position:relative;top:3px;left:auto;right:0;}'+
					//右侧过滤器样式
					'table.f-feature td:nth-child(3n+3){text-align:left;}'+
					'table.f-feature td:nth-child(3n+3) ul li a{padding:0;}'+
					'table.f-feature td:nth-child(3n+3) ul li a i{margin:0 4px 0 0;position:relative;top:3px;left:0;right:auto;}'+
					//右侧过滤器计数样式
					'a.filterN span.goodsCount{background-color:rgba(226,58,58,0.3);}'+
					'a.filterN:hover span.goodsCount{background-color:#e23a3a;}'+
					//自定义匹配
					'#regFilter{margin:0 5px;}'+
					'#regFilter .txt{margin:5px 0;padding:0 2px;width:50%;border:1px solid #E7E3E7;font-size:12px;color:#666;}'+
					'.gl-item .p-name em b{font-weight:normal;}'+
					'.gl-item .p-name em .hl1{background:hsla(0,100%,50%,0.5);}'+
					'.gl-item .p-name em .hl2{background:hsla(200,100%,50%,0.5);}'+
					'.gl-item .p-name em .hl3{background:hsla(40,100%,50%,0.5);}'+
					'.gl-item .p-name em .hl4{background:hsla(240,100%,50%,0.5);}'+
					'.gl-item .p-name em .hl5{background:hsla(80,100%,50%,0.5);}'+
					'.gl-item .p-name em .hl6{background:hsla(280,100%,50%,0.5);}'+
					'.gl-item .p-name em .hl7{background:hsla(120,100%,50%,0.5);}'+
					'.gl-item .p-name em .hl8{background:hsla(320,100%,50%,0.5);}'+
					'.gl-item .p-name em .hl9{background:hsla(160,100%,50%,0.5);}'+
					//动作条按钮
					'#moreFiltersPanel a.btn.btn-default{margin:5px;}'+
					'#moreFiltersPanel a.btn.btn-default.btn-icon{padding:4px 5px;}'+
					'#moreFiltersPanel a.btn-icon{margin:5px;height:25px;}'+
					//动作条checkbox
					'#moreFiltersPanel .ckbox{margin:1px 0 0 6px;}'+
					//动作条图标
					'#actionBar i{display:inline-block;width:25px;height:25px;background:url(https://misc.360buyimg.com/user/passport/1.0.0/widget/login-form-2016-1124/i/qr-coagent.png) no-repeat;}'+
					//动作条提示
					'#actionBar i.info{margin:0 5px;background-position-x:-27px;}'+
					'#actionBar #infoLog{color:blue;font-weight:bold;}'+
					//动作条下拉选择框
					'#actionBar select{padding:0 20px 0 3px;border:1px solid #E7E3E7;font-size:12px;color:#666;-webkit-appearance: none;background:url(//misc.360buyimg.com/product/list/1.0.7/css/i/search.ele.png) no-repeat 78px 5px;}'+
					'#actionBar select:hover{background-position-y:-12px;}'+
					//被过滤商品的样式
					'li.gl-item:hover{filter:none;}'+
					'li.gl-item:hover .gl-i-wrap .p-img{filter:none;}'+
					//样式0:淡化
					'li.akari{background-color:#fff;filter:opacity(10%);}'+
					'li.akari:hover .gl-i-wrap div{filter:opacity(30%);}'+
					'.goods-list-v1 .gl-item.akari:hover{border-color:#ccc;}'+
					'.goods-list-v2 .gl-item.akari:hover .gl-i-wrap {border-color:#ccc;}'+
					//样式1:隐藏
					'li.haruhi{display:none;}'+
					//样式2:边框
					'li.cirno{background-color:#fff;}'+
					'li.cirno:hover .gl-i-wrap div{filter:opacity(30%);}'+
					'.goods-list-v1 .gl-item.cirno{border-color:#000;}'+
					'.goods-list-v1 .gl-item.cirno:hover{border-color:#48f;}'+
					'.goods-list-v2 .gl-item.cirno .gl-i-wrap {border-color:#000;}'+
					'.goods-list-v2 .gl-item.cirno:hover .gl-i-wrap {border-color:#48f;}'+
					//样式3:黑白
					'li.yuno{background-color:#fff;filter:grayscale(100%) brightness(60%);}'+
					'li.yuno:hover .gl-i-wrap div{filter:grayscale(100%);}'+
					'.goods-list-v1 .gl-item.yuno:hover{border-color:#888;}'+
					'.goods-list-v2 .gl-item.yuno:hover .gl-i-wrap {border-color:#888;}'+
					//样式4:转色
					'li.mizuki{background-color:#fff;filter:hue-rotate(180deg);}'+
					'li.mizuki:hover .gl-i-wrap div{filter:hue-rotate(180deg);}'+
					'.goods-list-v1 .gl-item.mizuki:hover{border-color:#3af;}'+
					'.goods-list-v2 .gl-item.mizuki:hover .gl-i-wrap {border-color:#3af;}'+
					//样式5:异端通通烧死
					'li.burnIt{background-color:#fff;filter:sepia(100%);}'+
					'li.burnIt:hover .gl-i-wrap div{filter:sepia(100%);}'+
					'.goods-list-v1 .gl-item.burnIt:hover{border-color:#e85;}'+
					'.goods-list-v2 .gl-item.burnIt:hover .gl-i-wrap {border-color:#e85;}'+
					//样式6:模糊
					'li.succubus{background-color:#fff;filter:blur(5px);}'+
					'li.succubus:hover .gl-i-wrap div{filter:blur(1.2px);}'+
					'.goods-list-v1 .gl-item.succubus:hover{border-color:#f3c;}'+
					'.goods-list-v2 .gl-item.succubus:hover .gl-i-wrap {border-color:#f3c;}'+
					//样式7:反色
					'li.conan{background-color:#fff;filter:invert(100%);}'+
					'li.conan:hover .gl-i-wrap div{filter:invert(100%);}'+
					'.goods-list-v1 .gl-item.conan:hover{border-color:#000;}'+
					'.goods-list-v2 .gl-item.conan:hover .gl-i-wrap {border-color:#000;}'+
					//样式8:暗刻
					'li.hphphp{background-color:#fff;filter:grayscale(10%) contrast(50) sepia(100%) saturate(100) hue-rotate(180deg) invert(100%) blur(1px);}'+
					'li.hphphp:hover .gl-i-wrap div{filter:grayscale(10%) contrast(50) sepia(100%) saturate(100) hue-rotate(180deg) invert(100%) blur(1px);}'+
					'.goods-list-v1 .gl-item.hphphp:hover{border-color:#000;}'+
					'.goods-list-v2 .gl-item.hphphp:hover .gl-i-wrap {border-color:#000;}'+
					''
				).id = 'styleGoodsFilters';
				//生成顶级过滤器HTML
				var uiPrependFilters = '';
				for (var i=0; i<jdGoodsFilters.length; ++i) {
					var f = jdGoodsFilters[i];
					if (f.level !== 0) continue; //剔除不是顶级的

					var checkedClass = f.checked ? 'class="selected"' : '';
					var checkedNClass = f.checkedN ? 'class="filterN selected"' : 'class="filterN"';
					uiPrependFilters +=
						'<li><a '+checkedClass+' href="javascript:;" id="goodsFilter'+f.name+'" filterId="'+i+'">'+
						'<i></i>'+f.name+'<span class="goodsCount" id="goodsCount'+f.name+'">0</span>'+
						'</a></li>'+
						'<li><a '+checkedNClass+' href="javascript:;" id="goodsFilter'+f.nameN+'" filterId="'+i+'">'+
						'<i></i>'+f.nameN+'<span class="goodsCount" id="goodsCount'+f.nameN+'">0</span>'+
						'</a></li>';
				}
				//生成【下级过滤器】按钮HTML
				uiPrependFilters +=
					'<li class="showMoreFilters">'+
					'<a id="showMoreFiltersPanel" href="javascript:;">'+
					'下级过滤器'+
					'<span id="moreFiltersCount" class="zeroFiltersCount" style="display:none;">0</span>'+
					'</a>'+
					'</li>';
				//添加顶级过滤器和【下级过滤器】按钮
				uiPos.first().prepend($(uiPrependFilters));
				//保存控件引用
				unsafeWindow.y$.aShowMoreFiltersPanel = $(document.getElementById('showMoreFiltersPanel'));
				unsafeWindow.y$.spanMoreFiltersCount = $(document.getElementById('moreFiltersCount'));
				//更新过滤器计数
				var spanMoreFiltersCount = updateUsingMoreFiltersCount(); //添加顶级过滤器和【下级过滤器】按钮
				//安装顶级过滤器响应函数
				installFilterClickHandler(0);
				//安装【下级过滤器】按钮响应函数
				unsafeWindow.y$.aShowMoreFiltersPanel.click(function() {
					setTimeout(toggleMoreFiltersPanel, 0);
				});
				//根据保存的设置打开下级过滤器面板
				if (GM_getValue('打开下级过滤器面板') !== undefined) toggleMoreFiltersPanel(true);
				//否则根据计数显示过滤器计数圆点
				else if (!spanMoreFiltersCount.hasClass('zeroFiltersCount')) spanMoreFiltersCount.css('display', ''); //初始化不用动画
				//安装过滤器响应函数
				function installFilterClickHandler(level) {
					for (var i=0; i<jdGoodsFilters.length; ++i) {
						var f = jdGoodsFilters[i];
						if (f.level !== level) continue; //剔除不是传入等级的

						//绑定HTML元素
						f.aFilter = document.getElementById('goodsFilter'+f.name);
						f.spanFilterCount = document.getElementById('goodsCount'+f.name);
						f.aFilterN = document.getElementById('goodsFilter'+f.nameN);
						f.spanFilterNCount = document.getElementById('goodsCount'+f.nameN);
						//初始化标记
						f.created = true;

						//安装点击响应函数
						f.aFilter.addEventListener('click', filterClickHandler);
						f.aFilterN.addEventListener('click', filterClickHandler);
					}
					//过滤器点击响应函数
					function filterClickHandler() {
						if (undefined !== unsafeWindow.z$.currentFilterData) return; //防止重入
						unsafeWindow.z$.currentFilterData = this || event.currentTarget || arguments[0].currentTarget;
						setTimeout(function() {
							var aFilter = unsafeWindow.z$.currentFilterData;
							var cl = aFilter.classList;
							cl.toggle('selected');
							var checked = cl.contains('selected');
							var filterN = cl.contains('filterN');
							var f = jdGoodsFilters[aFilter.getAttribute('filterId')];
							if (filterN) f.checkedN = checked;
							else f.checked = checked;
							if ((filterN ? f.goodsCountFilteredN+f.goodsCountN : f.goodsCountFiltered+f.goodsCount) !== 0) applyGoodsFilters(); //过滤器点击响应
							//更新过滤器计数
							if (f.level === 1) updateUsingMoreFiltersCount(); //过滤器点击响应
							//保存设置
							var valName = filterN ? f.nameN : f.name;
							if (checked) GM_deleteValue(valName); else GM_setValue(valName, true);
							delete unsafeWindow.z$.currentFilterData;
						}, 0);
					}
				}
				//打开/关闭下级过滤器面板
				function toggleMoreFiltersPanel(isInitializing) {
					if (!isInitializing) saveStates();
					var div = unsafeWindow.y$.divMoreFiltersPanel;
					if (div === undefined) {
						setupMoreFiltersPanel();
						div = unsafeWindow.y$.divMoreFiltersPanel;
					}
					var span = unsafeWindow.y$.spanMoreFiltersCount;
					if (unsafeWindow.y$.aShowMoreFiltersPanel.toggleClass('opened').hasClass('opened')) {
						//保存下级过滤器面板打开状态
						GM_setValue('打开下级过滤器面板', true);
						//显示下级过滤器面板
						if (isInitializing || unsafeWindow.x$.noAnimateChecked) { //不允许动画
							div.css('display', '');
							if (!span.hasClass('zeroFiltersCount')) span.css('display', 'none');
						} else {
							div.slideDown('fast');
							if (!span.hasClass('zeroFiltersCount')) span.fadeOut();
						}
					} else {
						//保存下级过滤器面板关闭状态
						GM_deleteValue('打开下级过滤器面板');
						//结束正在执行的提醒动画
						$('#moreFiltersPanel td:has(a[filterId])').finish(); //querySelectorAll 不支持 :has
						//关闭下级过滤器面板
						if (isInitializing || unsafeWindow.x$.noAnimateChecked) { //不允许动画
							div.css('display', 'none');
							if (!span.hasClass('zeroFiltersCount')) span.css('display', '');
						} else {
							div.slideUp('fast');
							if (!span.hasClass('zeroFiltersCount')) span.fadeIn();
						}
					}
					//向页面添加下级过滤器面板
					function setupMoreFiltersPanel() {
						var uiFilters = [];
						//生成过滤器HTML数组
						for (var i=0; i<jdGoodsFilters.length; ++i) {
							var f = jdGoodsFilters[i];
							if (f.level !== 1) continue; //剔除不是下级的

							var checkedClass = f.checked ? 'class="selected"' : '';
							var checkedNClass = f.checkedN ? 'class="filterN selected"' : 'class="filterN"';
							uiFilters.push({
								name: f.name,
								filter: '<li><a '+checkedClass+' href="javascript:;" id="goodsFilter'+f.name+'" filterId="'+i+'" title="【'+f.name+'】商品">'+
								'<span class="goodsCountPlaceholder"><span class="goodsCount" id="goodsCount'+f.name+'">0</span></span><i></i>'+
								'</a></li>',
								filterN: '<li><a '+checkedNClass+' href="javascript:;" id="goodsFilter'+f.nameN+'" filterId="'+i+'" title="【'+f.nameN+'】商品">'+
								'<i></i><span class="goodsCountPlaceholder"><span class="goodsCount" id="goodsCount'+f.nameN+'">0</span></span>'+
								'</a></li>'
							});
						}
						//计算过滤器表格列数
						var cols = 6;
						//生成过滤器表格内容HTML
						var filtersTableRows = '';
						for (var j=0; j<uiFilters.length; j+=cols) {
							filtersTableRows += '<tr>';
							for (var k=0; k<cols; ++k) {
								var l = j + k;
								if (l < uiFilters.length) {
									var m = uiFilters[l];
									filtersTableRows += '<td><ul>'+m.filter+'</ul></td><td>'+m.name+'</td><td><ul>'+m.filterN+'</ul></td>';
								} else filtersTableRows += '<td></td><td></td><td></td>';
							}
							filtersTableRows += '</tr>';
						}
						//向页面添加过滤器表格
						document.getElementById('J_filter').insertAdjacentHTML('beforeend',
							'<div id="moreFiltersPanel" class="filter" style="display:none;">'+
								'<table class="f-feature" style="float:none;">'+filtersTableRows+'</table>'+
								'<hr>'+
								'<div id="regFilter">'+
									'<div style="flex-grow:1;">'+
										'<a target="_blank" href="https://www.bilibili.com/video/av15760606" style="color:transparent;text-shadow:transparent 0 0 0!important;">国际通用手势教程</a>'+
										'</div>'+
									'<div style="flex-grow:1;">'+
										'<label for="goodsPattern" title="过滤商品名【包含指定字串】或【匹配指定正则表达式】的商品">商品名匹配规则:</label><input id="goodsPattern" class="txt" type=text title="键入【回车】或点击【手动更新过滤结果】以应用商品名匹配规则"></input>'+
										'<input class="ckbox" id="useRegex" type="checkbox"><label for="useRegex" title="'+
											'普通模式:\n'+
											'支持搜索多个值,以反引号【`】分隔值列表,\n'+
											'值列表以反引号开头采用同时命中规则(AND),\n'+
											'否则采用任一命中规则(OR)\n'+
											'\n'+
											'正则模式:【程序猿&攻城狮专用 ◕◡◕✧】\n'+
											'支持 js 正则语法(正斜线分隔)\n'+
											'非正则语法的情况下默认追加 igm 标志'+
											'">正则</label>'+
										'<input class="ckbox" id="highlightGoodsPattern" type="checkbox"><label for="highlightGoodsPattern">高亮</label>'+
										'</div>'+
									'<div style="flex-grow:1;">'+
										'<a target="_blank" href="https://www.bilibili.com/video/av17978378" style="color:transparent;text-shadow:transparent 0 0 0!important;">脸控福利</a>'+
										'</div>'+
									'</div>'+
								'<hr>'+
								'<div id="actionBar">'+
									'<a id="allFiltersReset" class="btn btn-default" href="javascript:;">重置全部过滤器</a>'+
									'<a id="moreFiltersReset" class="btn btn-default" href="javascript:;">重置下级过滤器</a>'+
									'<a id="highlightFilters" class="btn btn-default" href="javascript:;">提醒一下?</a>'+
									'<a id="refreshCount" class="btn btn-default" href="javascript:;" title="'+
										'一般情况下过滤结果都是正确的,但是不排除因为\n'+
										'网络/缓存以及插件本身的 bug 等问题而可能导致\n'+
										'过滤结果不准确或者出现各种莫名其妙的错误,\n'+
										'此时可尝试手动更新过滤结果。'+
										'">手动更新过滤结果</a>'+
									'<div style="flex-grow:1;">'+
										'<div style="display:none;">'+
											'<i class="info"></i><label id="infoLog"></label>'+
											'</div>'+
										'</div>'+
									'<select id="goodsFilterMode">'+
										'<option value="0" selected>淡化</option>'+
										'<option value="1">隐藏</option>'+
										'<option value="2">边框</option>'+
										'<option value="3">黑白</option>'+
										'<option value="4">转色</option>'+
										'<option value="5">异端通通烧死</option>'+
										'<option value="6">模糊</option>'+
										'<option value="7">反色</option>'+
										'<option value="8">暗刻</option>'+
										'</select>'+
									'<div>'+
										'<input id="filteredToLast" class="ckbox" type="checkbox"><label for="filteredToLast" title="o(* ̄3 ̄)o 过滤掉的商品扔到后面去">后排</label>'+
										'<input id="noAnimate" class="ckbox" type="checkbox"><label for="noAnimate" title="囧rz">老爷机不要动画!</label>'+
										'</div>'+
									'<a id="showSettings" class="btn-icon" href="javascript:;" title="一个神秘的按钮……'+
										'\n\n按钮背面刻着一串放荡不羁的狂草,'+
										'\n经过漫漫五千年的悠久岁月,'+
										'\n字迹已经被风化得几乎看不清楚:'+
										'\n【欲点此钮,后果自负 ◕◡◕✧】"><i></i></a>'+
									'</div>'+
								'</div>'
						);
						//保存控件引用
						unsafeWindow.y$.divMoreFiltersPanel = $(document.getElementById('moreFiltersPanel'));
						unsafeWindow.y$.inputGoodsPattern = $(document.getElementById('goodsPattern'));
						unsafeWindow.y$.checkboxUseRegex = $(document.getElementById('useRegex'));
						unsafeWindow.y$.checkboxHighlightGoodsPattern = $(document.getElementById('highlightGoodsPattern'));
						unsafeWindow.y$.aAllFiltersReset = $(document.getElementById('allFiltersReset'));
						unsafeWindow.y$.aMoreFiltersReset = $(document.getElementById('moreFiltersReset'));
						unsafeWindow.y$.aHighlightFilters = $(document.getElementById('highlightFilters'));
						unsafeWindow.y$.aRefreshCount = $(document.getElementById('refreshCount'));
						unsafeWindow.y$.labelInfoLog = $(document.getElementById('infoLog'));
						unsafeWindow.y$.selectGoodsFilterMode = $(document.getElementById('goodsFilterMode'));
						unsafeWindow.y$.checkboxFilteredToLast = $(document.getElementById('filteredToLast'));
						unsafeWindow.y$.checkboxNoAnimate = $(document.getElementById('noAnimate'));
						unsafeWindow.y$.aShowSettings = $(document.getElementById('showSettings'));
						//安装下级过滤器响应函数
						installFilterClickHandler(1);
						//显示下级过滤器面板之前更新计数
						applyGoodsFilters(true); //更新下级过滤器面板计数
						//正则模式
						var inputGoodsPattern = unsafeWindow.y$.inputGoodsPattern;
						if (unsafeWindow.x$.goodsPattern) inputGoodsPattern.val(unsafeWindow.x$.goodsPattern);
						inputGoodsPattern.change(function() {setTimeout(updateGoodsPattern, 0);});
						inputGoodsPattern.blur(function() {setTimeout(updateGoodsPattern, 0);});
						inputGoodsPattern.keypress(function(e) {
							if (e.keyCode === 13) {
								updateInfoLog('计算中……');
								unsafeWindow.y$.inputGoodsPattern.prop('disabled', true);
								setTimeout(function() {
									updateGoodsPattern();
									applyGoodsFilters();
									unsafeWindow.y$.inputGoodsPattern.prop('disabled', false);
									updateInfoLog('');
								}, 0);
							}
						});
						//设置checkbox【正则匹配】值和响应函数
						if (unsafeWindow.x$.useRegexChecked) unsafeWindow.y$.checkboxUseRegex.prop('checked', true);
						unsafeWindow.y$.checkboxUseRegex.change(function() {
							setTimeout(function() {
								if (unsafeWindow.y$.checkboxUseRegex[0].checked) {
									unsafeWindow.x$.useRegexChecked = true; //操作更新
									GM_setValue('商品名匹配正则', true);
								} else {
									delete unsafeWindow.x$.useRegexChecked;
									GM_deleteValue('商品名匹配正则');
								}
								updateGoodsPattern(true);
								applyGoodsFilters();
							}, 0);
						});
						//设置checkbox【高亮匹配】值和响应函数
						if (unsafeWindow.x$.highlightGoodsPattern) unsafeWindow.y$.checkboxHighlightGoodsPattern.prop('checked', true);
						unsafeWindow.y$.checkboxHighlightGoodsPattern.change(function() {
							setTimeout(function() {
								if (unsafeWindow.y$.checkboxHighlightGoodsPattern[0].checked) {
									unsafeWindow.x$.highlightGoodsPattern = true; //操作更新
									GM_deleteValue('商品名匹配不高亮');
								} else {
									delete unsafeWindow.x$.highlightGoodsPattern;
									GM_setValue('商品名匹配不高亮', true);
								}
								applyGoodsFilters();
							}, 0);
						});
						//【重置全部过滤器】按钮响应函数
						unsafeWindow.y$.aAllFiltersReset.click(function() {
							resetGoodsFilters(true);
						});
						//【重置下级过滤器】按钮响应函数
						unsafeWindow.y$.aMoreFiltersReset.click(function() {
							resetGoodsFilters(false);
						});
						//【提醒】按钮响应函数
						unsafeWindow.y$.aHighlightFilters.click(function() {
							var filters = $('#moreFiltersPanel td:has(a[filterId])'); //querySelectorAll 不支持 :has
							var aside = filters.filter(':has(a.selected)');
							var bside = filters.not(':has(a.selected)');
							if (aside.length === 0 || bside.length === 0) return;
							filters.finish();
							(aside.length < bside.length ? aside : bside)
								.animate({backgroundColor:'#0cf'}, 100)
								.animate({backgroundColor:'rgba(0,204,255,0)'}, 5000, function() {
									this.removeAttribute('style');
								});
						});
						//【手动更新过滤结果】按钮响应函数
						unsafeWindow.y$.aRefreshCount.click(function() {
							updateInfoLog('计算中……');
							unsafeWindow.y$.aRefreshCount.prop('disabled', true);
							setTimeout(function() {
								saveStates();
								var t = Date.now();
								var updated = applyGoodsFilters(); //【手动更新过滤结果】按钮响应
								t = Date.now() - t;
								var aTag = unsafeWindow.y$.aRefreshCount;
								var title0 = aTag.attr('title0');
								if (title0 === undefined) {
									title0 = aTag.attr('title');
									aTag.attr('title0', title0);
								}
								var log = '上次计算耗时 '+t/1000+' 秒,'+(updated>0?('更新了 '+updated+' 项数据'):'没有需要更新的数据');
								aTag.attr('title', title0+'\n【'+log+'】');
								aTag.prop('disabled', false);
								updateInfoLog('');
							}, 30);
						});
						//设置infoLog的信息
						updateInfoLog(); //根据预设变量显示/隐藏infoLog
						//设置select值和响应函数
						unsafeWindow.y$.selectGoodsFilterMode.val(unsafeWindow.x$.goodsFilterModeIndex).change(function() {
							unsafeWindow.z$.goodsFilterModeNew = parseInt(event.currentTarget.value);
							if (unsafeWindow.z$.goodsFilterModeNew === unsafeWindow.x$.goodsFilterModeIndex) {
								delete unsafeWindow.z$.goodsFilterModeNew;
							} else setTimeout(function() {
								if (unsafeWindow.z$.goodsFilterModeNew === undefined) return;
								//改变当前过滤商品的样式
								var ca = unsafeWindow.x$.filterModes[unsafeWindow.z$.goodsFilterModeNew];
								var cr = unsafeWindow.x$.goodsFilterModeClass;
								document.querySelectorAll('li.gl-item.'+unsafeWindow.x$.goodsFilterModeClass).forEach(function(e) {
									e.classList.add(ca);
									e.classList.remove(cr);
								});
								//保存设置
								if (unsafeWindow.z$.goodsFilterModeNew === 0) GM_deleteValue('过滤方式');
								else GM_setValue('过滤方式', unsafeWindow.z$.goodsFilterModeNew);
								//更新值
								unsafeWindow.x$.goodsFilterModeIndex = unsafeWindow.z$.goodsFilterModeNew; //操作更新
								delete unsafeWindow.z$.goodsFilterModeNew;
								unsafeWindow.x$.goodsFilterModeClass = unsafeWindow.x$.filterModes[unsafeWindow.x$.goodsFilterModeIndex]; //操作更新
							}, 0);
						});
						//设置checkbox【后排】值和响应函数
						if (unsafeWindow.x$.filteredToLastChecked) unsafeWindow.y$.checkboxFilteredToLast.prop('checked', true);
						unsafeWindow.y$.checkboxFilteredToLast.change(function() {
							setTimeout(function() {
								if (unsafeWindow.y$.checkboxFilteredToLast[0].checked) {
									unsafeWindow.x$.filteredToLastChecked = true; //操作更新
									GM_setValue('后排', true);
									reorderGoodsByFilteredState();
								} else {
									delete unsafeWindow.x$.filteredToLastChecked;
									GM_deleteValue('后排');
									reorderGoodsByOriginalOrder();
								}
							}, 0);
						});
						//设置checkbox【关闭动画】值和响应函数
						if (unsafeWindow.x$.noAnimateChecked) unsafeWindow.y$.checkboxNoAnimate.prop('checked', true);
						unsafeWindow.y$.checkboxNoAnimate.change(function() {
							setTimeout(function() {
								if (unsafeWindow.y$.checkboxNoAnimate[0].checked) {
									unsafeWindow.x$.noAnimateChecked = true; //操作更新
									GM_setValue('老爷机不要动画', true);
								} else {
									delete unsafeWindow.x$.noAnimateChecked;
									GM_deleteValue('老爷机不要动画');
								}
							}, 0);
						});
						//神秘按钮
						unsafeWindow.y$.aShowSettings.click(function() {
							setTimeout(CheckSettings, 0);
						});

						//更新正则模式
						function updateGoodsPattern(modeSwitched) {
							var v = unsafeWindow.y$.inputGoodsPattern[0].value;
							var cond = unsafeWindow.x$.goodsPatternCondition;
							var hasPattern = v.length > 0;
							if (hasPattern) {
								if (!modeSwitched && v === unsafeWindow.x$.goodsPattern) return false;
								if (unsafeWindow.x$.useRegexChecked) {
									var rex = ToRegex(v);
									if (rex !== null) {
										cond.textRex = ToRegex(v);
										delete cond.textAny;
										delete cond.textAll;
									} else hasPattern = false;
								} else {
									var txtCond = ToTextCond(v);
									if (txtCond.txts.length > 0) {
										if (txtCond.allMatch) {
											cond.textAll = txtCond.txts;
											delete cond.textAny;
										} else {
											cond.textAny = txtCond.txts;
											delete cond.textAll;
										}
										delete cond.textRex;
									} else hasPattern = false;
								}
							}
							if (hasPattern) {
								unsafeWindow.x$.goodsPattern = v;
								GM_setValue('商品名匹配规则', v);
							} else {
								delete unsafeWindow.x$.goodsPattern;
								delete cond.textAny;
								delete cond.textAll;
								delete cond.textRex;
								GM_deleteValue('商品名匹配规则');
							}
						}
						//重置过滤器
						function resetGoodsFilters(all) {
							setTimeout(function() {
								for (var i=0; i<jdGoodsFilters.length; ++i) {
									var f = jdGoodsFilters[i];
									if (all ? f.level === undefined : f.level !== 1) continue; //重置全部,剔除未启用的;重置下级,剔除不是下级的

									if (!f.checked) {
										f.checked = true;
										GM_deleteValue(f.name);
									}
									if (!f.checkedN) {
										f.checkedN = true;
										GM_deleteValue(f.nameN);
									}
								}
								//结束正在执行的提醒动画
								$('#moreFiltersPanel td:has(a[filterId])').finish(); //querySelectorAll 不支持 :has
								//重置选中状态
								var n = document.querySelectorAll((all?'':'table')+'.f-feature a[filterId]:not(.selected)');
								for (var j=0; j<n.length; ++j) n[j].classList.add('selected');
								applyGoodsFilters(); //重置过滤器
							}, 0);
						}
					}
				}
				//保存设置
				function saveStates(noPanelState, noFiltersStates, noMisc) {
					//保存过滤器面板打开状态
					if (!noPanelState) {
						saveBoolIfDiff(unsafeWindow.y$.aShowMoreFiltersPanel.hasClass('opened'), '打开下级过滤器面板');
					}
					//保存过滤器状态
					if (!noFiltersStates) {
						for (var i=0; i<jdGoodsFilters.length; ++i) {
							var f = jdGoodsFilters[i];
							var sname = 'level'+f.name;
							if (GM_getValue(sname) !== f.level) {
								if (f.level !== undefined) GM_setValue(sname, f.level);
								else GM_deleteValue(sname);
							}
							if (GM_getValue(f.name)) {
								if (f.checked) GM_deleteValue(f.name);
							} else if (!f.checked) GM_setValue(f.name, true);
							if (GM_getValue(f.nameN)) {
								if (f.checkedN) GM_deleteValue(f.nameN);
							} else if (!f.checkedN) GM_setValue(f.nameN, true);
						}
					}
					//保存其他设置
					if (!noMisc) {
						//过滤方式
						saveIntIfDiff(unsafeWindow.x$.goodsFilterModeIndex, '过滤方式', true);
						//过滤掉的商品扔到后面去
						saveBoolIfDiff(unsafeWindow.x$.filteredToLastChecked, '后排');
						//关闭动画
						saveBoolIfDiff(unsafeWindow.x$.noAnimateChecked, '老爷机不要动画');
					}
					function saveIntIfDiff(i, gm_name, undefMeansZero) {
						var val = GM_getValue(gm_name);
						if (undefMeansZero) {
							if (val === undefined) val = 0;
							if (val !== i) {
								if (val === 0) GM_deleteValue(gm_name);
								else GM_setValue(gm_name, i);
							}
						} else if (val !== i) GM_setValue(gm_name, i);
					}
					function saveBoolIfDiff(b, gm_name) {
						if (GM_getValue(gm_name)) {
							if (!b) GM_deleteValue(gm_name);
						} else if (b) GM_setValue(gm_name, true);
					}
				}
			}
		}
		//更新【下级过滤器】的提示和过滤器计数蓝点
		function updateUsingMoreFiltersCount() {
			var moreFiltersTitle = '';
			var moreFiltersCount = 0;
			for (var i=0; i<jdGoodsFilters.length; ++i) {
				var f = jdGoodsFilters[i];
				if (f.level !== 1) continue; //剔除不是下级的

				if (f.checked === f.checkedN) {
					if (f.checked) continue;
					moreFiltersTitle += '\n同时隐藏了【'+f.name+'】和【'+f.nameN+'】商品所以你啥也看不见了 囧rz';
					moreFiltersCount += 2;
				} else {
					moreFiltersTitle += '\n隐藏【'+(f.checked ? f.nameN : f.name)+'】商品 '+
						(f.checked ?
							(f.goodsCountFilteredN === f.goodsCountN ?
								(f.goodsCountN === 0 ? '' : parentheses(f.goodsCountN)) :
								parentheses(f.goodsCountFilteredN+'/'+f.goodsCountN)) :
							(f.goodsCountFiltered === f.goodsCount ?
								(f.goodsCount === 0 ? '' : parentheses(f.goodsCount)) :
								parentheses(f.goodsCountFiltered+'/'+f.goodsCount)));
					++moreFiltersCount;
				}
			}
			var aShowMoreFiltersPanel = unsafeWindow.y$.aShowMoreFiltersPanel;
			var spanMoreFiltersCount = unsafeWindow.y$.spanMoreFiltersCount;
			if (moreFiltersCount > 0) {
				aShowMoreFiltersPanel.attr('title', '当前下级过滤器('+moreFiltersCount+'):'+moreFiltersTitle);
				spanMoreFiltersCount.text(moreFiltersCount);
				if (spanMoreFiltersCount.hasClass('zeroFiltersCount')) spanMoreFiltersCount.removeClass('zeroFiltersCount');
			} else {
				aShowMoreFiltersPanel.attr('title', '当前下级过滤器:无');
				spanMoreFiltersCount.text(0);
				if (!spanMoreFiltersCount.hasClass('zeroFiltersCount')) spanMoreFiltersCount.addClass('zeroFiltersCount');
			}
			return spanMoreFiltersCount;
		}
		//更新【状态栏】
		function updateInfoLog(log) {
			//将传入 log 和 unsafeWindow.x$.infoLogText 同步
			if (undefined === log) {
				log = unsafeWindow.x$.infoLogText;
			} else {
				if (log.length) unsafeWindow.x$.infoLogText = log;
				else delete unsafeWindow.x$.infoLogText;
			}
			//根据 log 的值操作 labelInfoLog
			var labelInfoLog = unsafeWindow.y$.labelInfoLog;
			if (labelInfoLog) {
				if (undefined === log || !log.length) labelInfoLog.parent().css('display', 'none');
				else labelInfoLog.text(log).parent().css('display', '');
			}
		}
		//应用过滤器,计算商品数量
		function applyGoodsFilters(setCountOnly) {
			var allGoods = document.querySelectorAll('li.gl-item');
			//计算商品属性
			calcGoodsProperties();
			//逐个更新过滤器
			var updatedCount = 0;
			for (var i=0; i<jdGoodsFilters.length; ++i) {
				var f = jdGoodsFilters[i];
				if (f.level === undefined) continue; //剔除未启用的
				//计算计数
				var goodsCount = getGoodsCount(f);
				var goodsCountN = allGoods.length - goodsCount;
				var filteredCount = getGoodsCountFiltered(f);
				//更新左侧过滤器
				var updated = updatedCount;
				if (f.goodsCount !== goodsCount) {
					f.goodsCount = goodsCount;
					++updatedCount;
				}
				if (f.goodsCountFiltered !== filteredCount[0]) {
					f.goodsCountFiltered = filteredCount[0];
					++updatedCount;
				}
				if (updatedCount > updated) {
					if (f.aFilter) updateFilterCount(f);
					updated = updatedCount;
				} else if (f.created) updateFilterCount(f);
				//更新右侧过滤器
				if (f.goodsCountN !== goodsCountN) {
					f.goodsCountN = goodsCountN;
					++updatedCount;
				}
				if (f.goodsCountFilteredN !== filteredCount[1]) {
					f.goodsCountFilteredN = filteredCount[1];
					++updatedCount;
				}
				if (updatedCount > updated) {
					if (f.aFilterN) updateFilterNCount(f);
				} else if (f.created) updateFilterNCount(f);
				//删除初始化标志
				if (f.created) delete f.created;
			}
			//更新【下级过滤器】的提示
			updateUsingMoreFiltersCount();
			//执行过滤器
			if (!setCountOnly) applyFilters();

			//返回更新的数据计数
			return updatedCount;

			function calcGoodsProperties() {
				for (var i=0; i<allGoods.length; ++i) {
					var g = allGoods[i];
					for (var j=0; j<jdGoodsFilters.length; ++j) {
						var f = jdGoodsFilters[j];
						if (f.level === undefined) continue; //剔除未启用的

						if (hitFilter(g, f)) g[f.name] = true;
						else delete g[f.name];
					}
				}
				function hitFilter(elem, filter) {
					for (var i=0; i<filter.conditions.length; ++i) {
						var cond = filter.conditions[i];
						if (goodsFilterMap[cond.type](elem, cond) ^ (cond.not !== undefined)) return true;
					}
					return false;
				}
			}
			function getGoodsCount(filter) {
				var count = 0;
				for (var i=0; i<allGoods.length; ++i) {
					if (allGoods[i][filter.name]) ++count;
				}
				return count;
			}
			function getGoodsCountFiltered(filter) {
				var filteredGoods = [];
				fg: for (var i=0; i<allGoods.length; ++i) {
					var g = allGoods[i];
					for (var j=0; j<jdGoodsFilters.length; ++j) {
						var f = jdGoodsFilters[j];
						if (f.level === undefined) continue; //剔除未启用的
						if (filter === f) continue; //剔除正在计数的

						if (f.checked === f.checkedN) {
							if (f.checked) continue; //忽略正反都显示的过滤器
							return [0, 0]; //有正反都不显示的过滤器,直接返回 0
						}

						if (g[f.name] ? f.checked : f.checkedN) continue; //测试通过

						continue fg;
					}
					filteredGoods.push(g);
				}
				var count = 0;
				for (var k=0; k<filteredGoods.length; ++k) {
					if (filteredGoods[k][filter.name]) ++count;
				}
				return [count, filteredGoods.length - count];
			}
			function updateFilterCount(filter) {
				filter.spanFilterCount.textContent = filter.goodsCountFiltered===filter.goodsCount ? filter.goodsCount : filter.goodsCountFiltered+'/'+filter.goodsCount;
				if (filter.goodsCountFiltered === 0) filter.aFilter.classList.add('zeroCountGoods');
				else filter.aFilter.classList.remove('zeroCountGoods');
			}
			function updateFilterNCount(filter) {
				filter.spanFilterNCount.textContent = filter.goodsCountFilteredN===filter.goodsCountN ? filter.goodsCountN : filter.goodsCountFilteredN+'/'+filter.goodsCountN;
				if (filter.goodsCountFilteredN === 0) filter.aFilterN.classList.add('zeroCountGoods');
				else filter.aFilterN.classList.remove('zeroCountGoods');
			}
			function applyFilters() {
				var inGoods = [];
				var outGoods = [];
				fg: for (var i=0; i<allGoods.length; ++i) {
					var g = allGoods[i];
					for (var j=0; j<jdGoodsFilters.length; ++j) {
						var f = jdGoodsFilters[j];
						if (f.level === undefined) continue; //剔除未启用的

						if (g[f.name]) {
							if (f.onPassed) f.onPassed(g);
						} else {
							if (f.onMissed) f.onMissed(g);
						}

						if (f.checked === f.checkedN) {
							if (f.checked) continue; //忽略正反都显示的过滤器
							var cf = unsafeWindow.x$.goodsFilterModeClass;
							for (var k=0; k<allGoods.length; ++k) allGoods[k].classList.add(cf); //正反都隐藏
							return;
						}

						if (g[f.name] ? f.checked : f.checkedN) continue; //测试通过
						//测试失败
						outGoods.push(g);
						continue fg;
					}
					inGoods.push(g);
				}
				var c = unsafeWindow.x$.goodsFilterModeClass;
				if (inGoods.length > 0) for (var l=0; l<inGoods.length; ++l) inGoods[l].classList.remove(c);
				if (outGoods.length > 0) for (var m=0; m<outGoods.length; ++m) outGoods[m].classList.add(c);
				if (unsafeWindow.x$.filteredToLastChecked) reorderGoodsByFilteredState(allGoods);
			}
		}
		//重排商品
		function reorderGoodsByFilteredState(allGoods) {
			if (undefined === allGoods) allGoods = document.querySelectorAll('li.gl-item');
			groupGoods(allGoods, function(x,y) {
				var xx = x.classList.contains(unsafeWindow.x$.goodsFilterModeClass);
				var yy = y.classList.contains(unsafeWindow.x$.goodsFilterModeClass);
				return xx === yy ? x.sortOrder-y.sortOrder : (xx?1:-1);
			});
		}
		function reorderGoodsByOriginalOrder(allGoods) {
			if (undefined === allGoods) allGoods = document.querySelectorAll('li.gl-item');
			groupGoods(allGoods, function(x,y) {
				return x.sortOrder-y.sortOrder;
			});
		}
		//将商品分组并记录原始顺序,然后对商品重新排序
		function groupGoods(allGoods, sortBy) {
			if (allGoods && allGoods.length) {
				var grouped = [];
				//分组
				for (var i=0; i<allGoods.length; ++i) {
					var goods = allGoods[i];
					var parent = goods.parentElement;
					var current = undefined;
					for (var j=0; j<grouped.length; ++j) {
						if (grouped[j].parent === parent) {
							current = grouped[j];
							break;
						}
					}
					if (!current) grouped.push(current = {parent: parent, goods:[]});
					//记录原始顺序
					if (undefined === goods.sortOrder) goods.sortOrder = current.goods.length;
					current.goods.push(goods);
				}
				//对每组商品单独排序
				for (var k=0; k<grouped.length; ++k) {
					var group = grouped[k];
					group.goods.sort(sortBy);
					$(group.parent).append(group.goods);
				}
			}
		}
		//加载所有商品
		function loadAllGoods() {
			if (unsafeWindow.SEARCH !== undefined && unsafeWindow.SEARCH.scroll !== undefined) {
				unsafeWindow.SEARCH.scroll();
				setTimeout(waitAllGoods, timerFreq);
			} else setTimeout(loadAllGoods, timerFreq);
			//等待所有商品加载完成
			function waitAllGoods() {
				if (unsafeWindow.SEARCH.loading) setTimeout(waitAllGoods, timerFreq);
				else processGoodsList();
			}
			//收尾处理
			function processGoodsList() {
				if (document.querySelectorAll('li.gl-item').length) {
					document.querySelector('div.notice-filter-noresult').remove();
				}
				forceLoadLazyImgs();
				applyGoodsFiltersOnLoaded();
				//取消图片延迟加载
				function forceLoadLazyImgs() {
					unsafeWindow.z$.forceLoadLazyImgsCount = 0;
					unsafeWindow.z$.forceLoadLazyImgsInterval = setInterval(function() {
						if (unsafeWindow.z$.forceLoadLazyImgsCount++ < 3) {
							var aName = 'data-lazy-img';
							document.querySelectorAll('ul.gl-warp img[data-lazy-img]:not([src])').forEach(function(img) {
								img.setAttribute('src', img.getAttribute(aName));
								img.removeAttribute(aName);
							});
							return;
						}
						if (unsafeWindow.z$.forceLoadLazyImgsInterval) {
							clearInterval(unsafeWindow.z$.forceLoadLazyImgsInterval);
							delete unsafeWindow.z$.forceLoadLazyImgsInterval;
						}
					}, 2000);
				}
				//延时应用过滤器
				function applyGoodsFiltersOnLoaded() {
					//每秒执行一次,前2次仅更新计数,15次后由 applyGoodsFiltersOnAjaxStop 接管,并计划一个10秒后的更新
					unsafeWindow.z$.applyGoodsFiltersOnLoadedCount = 0;
					unsafeWindow.z$.applyGoodsFiltersOnLoadedCountInterval = setInterval(function() {
						if (unsafeWindow.z$.applyGoodsFiltersOnLoadedCount < 15) {
							applyGoodsFilters(unsafeWindow.z$.applyGoodsFiltersOnLoadedCount++ < 2); //延迟收尾
							if (unsafeWindow.z$.applyGoodsFiltersOnLoadedCount === 3) updateInfoLog('');
							return;
						}
						if (unsafeWindow.z$.applyGoodsFiltersOnLoadedCountInterval) {
							clearInterval(unsafeWindow.z$.applyGoodsFiltersOnLoadedCountInterval);
							delete unsafeWindow.z$.applyGoodsFiltersOnLoadedCountInterval;
							setTimeout(applyGoodsFilters, 1000 * 10);
							applyGoodsFiltersOnAjaxStop();
						}
					}, 1000);
				}
				//ajaxStop收尾
				function applyGoodsFiltersOnAjaxStop() {
					//开始计时
					unsafeWindow.z$.goodsLoadedTime = Date.now();
					//注册 ajaxStop 事件
					unsafeWindow.$(document).ajaxStop(function() {
						var t = Date.now() - unsafeWindow.z$.goodsLoadedTime;
						if (t > 1000 * 15) return; //15秒之后不再响应该事件
						//console.log('ajaxStop -> '+t+'ms');

						//对挂起的操作重新计时(清除已有的并重新挂起一个新的延时操作)
						if (unsafeWindow.z$.applyGoodsFiltersTimeout !== undefined) {
							clearTimeout(unsafeWindow.z$.applyGoodsFiltersTimeout);
							delete unsafeWindow.z$.applyGoodsFiltersTimeout;
						}
						unsafeWindow.z$.applyGoodsFiltersTimeout = setTimeout(function() {
							delete unsafeWindow.z$.applyGoodsFiltersTimeout;
							applyGoodsFilters(); //ajaxStop 延时操作
						}, 33);
					});
				}
			}
		}
	}
	//检查保存数据的版本信息
	function CheckSettings(versionCheck) {
		var version = 50102; //每个子版本号占2位 //GM_info.script.version //用GM_info会使每个小版本更新都强行重置所有保存的设置
		if (versionCheck && GM_getValue('插件版本') >= version) return;
		var vals = GM_listValues();
		for (var i=0; i<vals.length; ++i) GM_deleteValue(vals[i]);
		GM_setValue('插件版本', version);
	}

	//圆括号包围字串
	function parentheses(str){return surround(str,'(',')');}
	function surround(str, prefix, suffix){return prefix+str+suffix;}
	//字串检测
	function isAny(str, vals) { //str∈vals
		for (var i=0; i<vals.length; ++i) {
			if (str === vals[i]) return true;
		}
		return false;
	}
	function includesAny(str, vals) { //∃v∈vals,str⊇v
		for (var i=0; i<vals.length; ++i) {
			if (str.includes(vals[i])) return true;
		}
		return false;
	}
	function includesAll(str, vals) { //∀v∈vals,str⊇v
		for (var i=0; i<vals.length; ++i) {
			if (!str.includes(vals[i])) return false;
		}
		return true;
	}
	//字串转 RegExp
	function ToRegex(str) {
		if (str[0] === '/') {
			try {
				var r = eval(str);
				if (r instanceof RegExp) return new RegExp(r); //重新调用一次 RegExp 对字面量进行优化
			} catch(e) {}
		}
		try { return new RegExp(str, 'gim'); } catch(e) {}
		return null;
	}
	//字串转匹配规则,去掉空白串
	function ToTextCond(str) {
		var allMatch = str[0] === '`';
		var vals = str.split('`');
		var txts = [];
		for (var i=allMatch?1:0; i<vals.length; ++i) {
			var txt = vals[i];
			if (txt.length > 0 && (txt = txt.trim()).length > 0) txts.push(txt);
		}
		return {allMatch:allMatch, txts:txts};
	}
	//高亮 HTML (Regex)
	function highlightHtmlUsingRegex(html, rex, hlInfo) {
		var i=0;
		rex.lastIndex = 0;
		html = html.replace(rex, function(m) {
			return m.length > 0 ? hlInfo.tag0[i++%9]+m+hlInfo.tag1 : '';
		});
		return i>0 ? html : null;
	}
	//高亮 HTML (string[])
	function highlightHtmlUsingTexts(html, txts, hlInfo) {
		if (txts.length === 0) return null;
		for (var i=0; i<txts.length; ++i) {
			var txt = txts[i];
			if (html.includes(txt)) html = html.replace(txt, hlInfo.tag0[i%9]+txt+hlInfo.tag1);
		}
		return html;
	}
	//高亮 HTML
	function highlightHtml(html, match, hlInfo) {
		return match instanceof RegExp ? highlightHtmlUsingRegex(html, match, hlInfo) : highlightHtmlUsingTexts(html, match, hlInfo);
	}
	//替换高亮 HTML
	function replaceHighlightHtml(html, match, hlMatch, hlInfo) {
		if (match instanceof RegExp) {
			if (hlMatch instanceof RegExp) { //正则替换正则
				if (match.source === hlMatch.source && match.flags === hlMatch.flags) return null; //相等的正则,跳过处理
			}
			html = unhighlightHtml(html, hlInfo);
			html = highlightHtmlUsingRegex(html, match, hlInfo);
		} else {
			if (hlMatch instanceof RegExp) {
				html = unhighlightHtml(html, hlInfo);
				html = highlightHtmlUsingTexts(html, match, hlInfo);
			} else { //数组替换数组
				var hit = false;
				for (var i=0; i<match.length; ++i) {
					var txt = match[i];
					var ti = i%9;
					if (i < hlMatch.length) {
						var hlTxt = hlMatch[i];
						if (txt === hlTxt) continue; //高亮的位置和内容相等,跳过处理
						html = html.replace(hlInfo.tag0[ti]+hlTxt+hlInfo.tag1, hlTxt); //先取消高亮
					}
					html = html.replace(txt, hlInfo.tag0[ti]+txt+hlInfo.tag1); //重新高亮
					hit = true;
				}
				if (match.length < hlMatch.length) {
					for (var j=match.length; j<hlMatch.length; ++j) {
						var hl = hlMatch[j];
						html = html.replace(hlInfo.tag0[j%9]+hl+hlInfo.tag1, hl);
					}
					hit = true;
				}
				return hit ? html : null;
			}
		}
		return html;
	}
	//取消高亮 HTML
	function unhighlightHtml(html, hlInfo) {
		for (var i=0; i<hlInfo.tag0.length; ++i) {
			html = html.replace(hlInfo.tag0[i], '');
		}
		return html.replace(hlInfo.tag1, '');
	}
}());