Ce script ne doit pas être installé directement. C'est une librairie destinée à être incluse dans d'autres scripts avec la méta-directive // @require https://update.greasyfork.org/scripts/438161/1009060/DoubanSearch.js
// ==UserScript==
// @name DoubanSearch
// @namespace http://tampermonkey.net/
// @version 1.0
// @description RT
// @author Pidanmeng
// @grant GM_openInTab
// @match *
// @include *
// @grant none
// ==/UserScript==
//豆瓣电影搜索助手
// 配置参数
let ev = null;
var text = window.getSelection().toString().trim();
document.addEventListener('mouseup', function (e) {
ev = e;//划词鼠标结束位置
});
const SettingOptions = {
defaultsearchengine: "db", // 默认搜索引擎
searchPattern: "automatic", // 搜索模式
selectPattern: "select", // 划词模式
selectKey: "Ctrl", // 划词键
selectIconPosition: "right", // 划词图标位置
};
// 图标
const Images = {
IconBase64: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAIAAABoJHXvAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDoyQjkwRDlGOTgyM0YxMUUyOTYyNEE4NkVDQjBDRTBENSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDoyQjkwRDlGQTgyM0YxMUUyOTYyNEE4NkVDQjBDRTBENSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjJCOTBEOUY3ODIzRjExRTI5NjI0QTg2RUNCMENFMEQ1IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjJCOTBEOUY4ODIzRjExRTI5NjI0QTg2RUNCMENFMEQ1Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+EQTxdwAAEetJREFUeNrsXQt4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',
DbSvg: '<svg t="1634541962091" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2799" width="16" height="16"><path d="M701.44 519.168l-382.976 0 0-191.488 382.976 0 0 191.488zM877.568 69.632q34.816 0 59.392 24.064t24.576 59.904l0 731.136q0 34.816-24.576 59.392t-59.392 24.576l-732.16 0q-34.816 0-58.88-24.576t-24.064-59.392l0-731.136q0-35.84 24.064-59.904t58.88-24.064l732.16 0zM187.392 197.632l648.192 0 0-63.488-648.192 0 0 63.488zM253.952 263.168l0 318.464 512 0 0-318.464-512 0zM857.088 774.144l-176.128 0 62.464-111.616-70.656-53.248q-5.12 12.288-9.216 23.552t-9.728 23.552-11.776 23.552q-17.408 29.696-31.744 57.856t-19.456 36.352l-158.72 0q-4.096-8.192-18.432-36.352t-31.744-57.856q-7.168-11.264-12.288-23.552t-9.216-23.552-9.216-23.552l-70.656 53.248 62.464 111.616-176.128 0 0 65.536 690.176 0 0-65.536z" p-id="2800" fill="#4da64d"></path></svg>',
ImdbSvg: '<svg t="1634544643843" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3906" width="16" height="16"><path d="M864 64H160C107 64 64 107 64 160v704c0 53 43 96 96 96h704c53 0 96-43 96-96V160c0-53-43-96-96-96zM106.6 458.4H106c0.2-0.2 0.4-0.6 0.6-0.8zM258 639.6H192V384h66z m226.4 0h-57.4v-172.8l-23.2 172.8h-41.2l-24.4-169v169h-58V384h85.6c6.6 39.6 12 79.8 17.4 119.8l15.2-119.8h86z m22.8 0V384h49.2c35.2 0 89.4-3.2 98 41.8 3.4 15.2 2.8 32.6 2.8 48.8 0 177 22.2 165.2-150 165z m321.8-58.4c0 31.4-4.8 61.8-44.4 61.8-18 0-30.4-6-41.8-19.6l-3.8 16.2h-59.6V384h63.4v83.4c12-13 24-18.4 41.8-18.4 42.8 0 44.4 25.6 44.4 60.2zM594 459.8c0-19.4 3.2-32-20.6-32v167.4c24.4 0.6 20.6-17.4 20.6-36.8z m171 52.2c0-10.8 2.2-25.4-12.4-25.4-12 0-9.8 17.8-9.8 25.4 0 1.2-2.2 79.2 2.2 89.4 1.6 3.2 4.4 4.8 7.6 4.8 15.6 0 12.4-18 12.4-28.8z" p-id="3907" fill="#f4ea2a"></path></svg>',
MovieIconBase64: 'data:image/png;base64,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',
BookIconBase64: 'data:image/png;base64,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',
VideoDefaultImg: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEEAAABbCAYAAAAsuui4AAAAAXNSR0IArs4c6QAAA3VJREFUeAHtmw1PMjEQhIuACEII//9PGuUbhdenl2kOEol8bI2vswl3ba8t3enMbrlo5/X19ZD+uD38cf+z+wbhEwaDYBCaYGAmmAlmQoOAmWAmmAkFAcvBcihk8DnBcrAcLIeCgOVgORQyODtYDpaD5VAQsBwsh0IGZwfLwXKwHAoClkMDRa+NSM3y+/t72m63ab/fp263mwaDQXp4+Jk4/SMgrNfrtFwujzCnbTwep36/f9Reo1Id+o+PjwwAuz+dTtNsNkuTyST7Op/P0+FQ/88lqoEA7VerVcJR7Pn5Ocug0+nk3R8OhxmAxWKRdrtd7lPrUkUOOHW6yzChbb1esxTiBJ/Hx8cMFCBFWzgI0JvdxaC9nD11DlCQBv2JFwBB36enp2gMYv9IA4c2m03OANCdoIfzpwDgpdrJEEiFusZGoxAWEwAACSgLnNL/nGMAAAsIoi8vL4nMEWlhcmAXiQXkf1hw6RkANiiTACQgRqXPMBDQNMaO3hLtAREQYMOvA4GUiCko5soNF1gRZWFMgAGwQQehWxx4e3srWeWWeb4aGwaCAiGxQOWvFnGuXQy4ZY5z8/MsHAScwAFYwY8mdE0djQMQ5wDKyIcy/YkhMIkDUw0QwlKkdk5O4BjOUsdhymQQjLuA4DllBVON13x5wJ0vYUxQSpQTOiixw2KA+pABAIY6z2EEd0zj1ffO/ufpwkDgwMPuyQmozUc2Go1UPDoaCwg9ZDxtzBdlYXJgwW0QrnUAhkRKgXWFgiAK48g1xjiO378aBC1ekrgUCI3TPJeO/27/UCZo8XLmu4tSP43TPGq/9z0sMLJQLV7OQG/OC8iEIMm5gQ/9yB48ow/P6KNxktW9ndd8oUwgoredwSl+DPGaDeMsQB3nMdqpy3kA0Ry5Q9AllAmsmV1mtzExQAzhzq7rTEAZALTzlNU3TxB0qQICO86u4hCv1WU4zUfGewcZWYExUT+f9T3cq4DAF0H5tsO0nTMdm/8LJuC4tI7eLzHiwSXAXTJ3u2+nxj+Htl+4tr/8XFnxQ/HhXN9bn4XLgQWyozVenV8LRmiKvHZRtccZhE/EDYJBaIRnJpgJZkKDgJlgJpgJBQHLwXIoZPA5wXKwHCyHgoDlYDkUMjg7WA6Wg+VQELAcLIdCBmcHy8FysBwKApaD5VDI4OxgOTRk+AcCjnlZW2tDmAAAAABJRU5ErkJggg==',
}
// 链接
const Urls = {
DbMoviePageUrl: 'https://movie.douban.com',
ImDbVideoPageUrl: 'https://www.imdb.com',
DbVideoInfoPageUrl: 'https://movie.douban.com/subject/{subjectId}', // 豆瓣视频详情页面
DbBookPageUrl: 'https://book.douban.com',
DbBookInfoPageUrl: 'https://book.douban.com/subject/{subjectId}', // 豆瓣读书详情页面
ImdbVideoInfoPageUrl: 'https://www.imdb.com/title/{imdbId}', // imdb 视频详情页面
DbVideoSearchResultPageUrl: 'https://www.douban.com/search?cat=1002&q={title}', // 豆瓣电影搜索结果页面
DbBookSearchResultPageUrl: 'https://www.douban.com/search?cat=1001&q={title}', // 豆瓣读书搜索结果页面
MovieSearchResultPageUrl: 'https://movie.douban.com/subject_search?search_text={title}',
BookSearchResultPageUrl: 'https://book.douban.com/subject_search?search_text={title}',
DbVideoSearchApiUrl: 'https://www.douban.com/j/search?q={title}&cat=1002', // 豆瓣电影官方搜索接口
DbBookSearchApiUrl: 'https://www.douban.com/j/search?q={title}&cat=1001', // 豆瓣读书官方搜索接口
IframePageHost: 'https://yyy.rth1.me', // 取词遮罩地址 使用的热铁盒网页托管
ImgHandleUrl: 'https://images.weserv.nl/?url={url}', // 图片处理接口 可以缓存、修改图片尺寸等 本脚本用来防止图片跨域
DbImdbApiUrl: 'https://movie.querydata.org/api?id={subjectId}', // 可以获取豆瓣-imdb-烂番茄信息的聚合接口 api来自https://github.com/iiiiiii1/douban-imdb-api
}
const Logger = {
debug: console.debug,
log: console.log,
info: console.info,
warn: console.warn,
error: console.error
}
const Utils = {
/**
* 字符串模板格式化
* @param {string} formatStr - 字符串模板
* @returns {string} 格式化后的字符串
* @example
* Utils.StringFormat("ab{0}c{1}ed",1,"q") output "ab1cqed"
*/
StringFormat: function (formatStr) {
let args = arguments;
return formatStr.replace(/\{(\d+)\}/g, function (m, i) {
i = parseInt(i);
return args[i + 1];
});
},
/**
* 日期格式化
* @param {Date} date - 日期
* @param {string} formatStr - 格式化模板
* @returns {string} 格式化日期后的字符串
* @example
* Utils.DateFormat(new Date(),"yyyy-MM-dd") output "2020-03-23"
* @example
* Utils.DateFormat(new Date(),"yyyy/MM/dd hh:mm:ss") output "2020/03/23 10:30:05"
*/
DateFormat: function (date, formatStr) {
let o = {
"M+": date.getMonth() + 1, //月份
"d+": date.getDate(), //日
"h+": date.getHours(), //小时
"m+": date.getMinutes(), //分
"s+": date.getSeconds(), //秒
"q+": Math.floor((date.getMonth() + 3) / 3), //季度
"S": date.getMilliseconds() //毫秒
};
if (/(y+)/.test(formatStr)) {
formatStr = formatStr.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
}
for (let k in o) {
if (new RegExp("(" + k + ")").test(formatStr)) {
formatStr = formatStr.replace(
RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
}
}
return formatStr;
},
// 获取配置参数
GetSettingOptions: function () {
let optionsJson = GM_getValue("db-search-options") || "";
if (optionsJson != "") {
let optionsData = JSON.parse(optionsJson);
for (let key in SettingOptions) {
if (SettingOptions.hasOwnProperty(key) && optionsData.hasOwnProperty(key)) {
SettingOptions[key] = optionsData[key];
}
}
}
return SettingOptions;
},
// 设置配置参数
SetSettingOptions: function () {
let optionsJson = JSON.stringify(SettingOptions);
GM_setValue("db-search-options", optionsJson);
},
/**
* 人员格式化
* @param {Array} personList - 人员数组
* @param {Number} len - 需要的数量
* @returns {String} 格式化后的字符串
* @example
* Utils.FmtDbPerson([{name: '张 zhang'},{name: '王 wang'},{name: '李 li'}],2) output "张/王"
* Utils.FmtDbPerson([{data: [{name: '张'}]},{data: [{name: '王'}]},{data: [{name: '李'}]}],2) output "张/王"
*/
FmtDbPerson: function (personList, len) {
if (personList && personList.length > 0) {
if (len && personList.length > len) {
personList = personList.slice(0, len);
}
let nameArr = [];
personList.forEach((item) => {
if (item.hasOwnProperty('data')) { // db2使用
nameArr.push(item.data[0].name);
} else {
nameArr.push(item.name.split(' ')[0]); // db使用
}
})
return nameArr.join(' / ');
}
return '';
},
/**
* 解析视频列表 dom 元素
* @param {Document} htmlDoc - 视频列表dom
* @param {String} selector - 选择器
* @returns {[VideoInfo]} 视频列表数组
* @example
* Utils.ParseVideoListDom(document.getElementById('a'),'li') output [{videoInfo},{videoInfo},...]
*/
ParseVideoListDom: function (htmlDoc, selector) {
let videoList = [];
let bookList = [];
if (htmlDoc) {
let liDoc = $(htmlDoc).find(selector);
liDoc.each((index, item) => {
let titleADom = $(item).find('.title a');
let title = titleADom.html() || '';
let onclickStr = titleADom.attr("onclick"); // moreurl(this,{i: '14', query: 'hh', from: 'dou_search_movie', sid: 25741647, qcat: '1002'})
let id = 0;
if (onclickStr) {
id = onclickStr.split(',')[4].replace(/[^0-9]/ig, '');
}
let image = $(item).find('img').attr("src");
let cast = ($(item).find('.subject-cast').html() || '').replace('/ / ', '/').replace(/原名:(.*?)\//g, '');
let socreDoc = $(item).find('.rating_nums');
let score = socreDoc.html() || '';
let ratingCount = '';
if (score && socreDoc.next() && socreDoc.next().html()) {
let count = socreDoc.next().html().replace(/[^0-9]/ig, '');
if (count) {
ratingCount = `${count} 人参与评分`;
}
}
let videoInfo = {
subjectId: id,
image: Urls.ImgHandleUrl.replace('{url}', encodeURIComponent(image)),
url: Urls.DbVideoInfoPageUrl.replace('{subjectId}', id),
description: $(item).find('p').html() || '',
title, score, ratingCount, cast: cast,
}
videoList.push(videoInfo);
let bookInfo = {
subjectId: id,
image: Urls.ImgHandleUrl.replace('{url}', encodeURIComponent(image)),
url: Urls.DbBookInfoPageUrl.replace('{subjectId}', id),
description: $(item).find('p').html() || '',
title, score, ratingCount, cast: cast,
}
bookList.push(bookInfo);
});
}
return videoList;
},
/**
* 解析String 为 dom 元素
* @param {String} text - 文档字符
* @returns {Document} 文档对象
* @example
* Utils.ParseDomFromString('<div>a</div>') output Document
*/
ParseDomFromString: function (text) {
if (!text) {
return new Document();
}
let parser = new DOMParser();
return parser.parseFromString(text, "text/html");
},
//查找第5次出现/索引
findStrIndex: function(str, cha, num) {
var x = str.indexOf(cha);
for (var i = 0; i < num-1; i++) {
x = str.indexOf(cha, x + 1);
}
return x;
},
}
// 随机因子 用于元素属性后缀 以防止属性名称重复
const randomCode = Utils.DateFormat(new Date(), "yyMM").toString() + (Math.floor(Math.random() * 900000) + 100000).toString();
// 豆瓣搜索引擎1 爬虫模式
const DoubanMovieSearchByDom = {
code: "db",
codeText: "豆瓣",
SearchVideoList: function (title) {
return new Promise((resolve, reject) => {
if (!title) {
resolve([]);
}
GM_xmlhttpRequest({
method: "GET",
url: Urls.DbVideoSearchResultPageUrl.replace('{title}', encodeURIComponent(title)),
onload: function (response) {
let videoList = [];
if (response.status == 200) {
let htmlDoc = Utils.ParseDomFromString(response.responseText);
videoList = Utils.ParseVideoListDom(htmlDoc, '.result-list .result');
} else {
Logger.warn('查询失败,title:' + title, response.statusText);
}
resolve(videoList);
}
});
})
},
SearchVideoInfo: function (subjectId) {
let self = this;
return new Promise((resolve, reject) => {
if (!subjectId) {
resolve(null);
}
let url = Urls.DbVideoInfoPageUrl.replace('{subjectId}', subjectId);
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function (response) {
if (response.status == 200) {
let doubanInfo = {};
let htmlDoc = Utils.ParseDomFromString(response.responseText);
if (htmlDoc) {
let ldJsonDb = $(htmlDoc).find('script[type="application/ld+json"]');
let ldJsonDbOthers = $(htmlDoc).find('meta[name="keywords"]'); //中文标题
let ldJsonDbScri = $(htmlDoc).find('span[property="v:summary"]');
let ldJsonDbAttrs = $(htmlDoc).find('span[class="attrs"]');
let ldJsonDbDirector = ldJsonDbAttrs[0].innerText;
if(ldJsonDbAttrs[2]) {
if(ldJsonDbAttrs[2].innerText.split('/').length > 7) {
ldJsonDbAttrs = ldJsonDbAttrs[2].innerText.slice(0, Utils.findStrIndex(ldJsonDbAttrs[2].innerText, "/", 6)) + "/ 更多…"
} else {
ldJsonDbAttrs = ldJsonDbAttrs[2].innerText;
}
} else {
ldJsonDbAttrs =ldJsonDbAttrs[1].innerText;
}
if (ldJsonDb && ldJsonDb.length > 0 && ldJsonDb[0].innerText) {
try {
doubanInfo = JSON.parse(ldJsonDb[0].innerText.replace(/\r\n/g, '').replace(/\n/g, ''));
//console.log(htmlDoc);
let videoInfo = {
//title: doubanInfo.name,
title: ldJsonDbOthers[0].content.split(',')[0],
image: Urls.ImgHandleUrl.replace('{url}', encodeURIComponent(doubanInfo.image)),
url: Urls.DbMoviePageUrl + doubanInfo.url,
//description: doubanInfo.description,
description: ldJsonDbScri[0].innerText.replace(/\r\n/g, '').replace(/\n/g, '').trim(),
//director: Utils.FmtDbPerson(doubanInfo.director, 2),
director: ldJsonDbDirector,
//actor: Utils.FmtDbPerson(doubanInfo.actor, 6),
actor: ldJsonDbAttrs,
score: doubanInfo.aggregateRating.ratingValue,
ratingCount: doubanInfo.aggregateRating.ratingCount,
genre: doubanInfo.genre.join(' / '),
time: doubanInfo.datePublished,
}
// 获取imdbId
let imdb_anchor = $(htmlDoc).find('#info span.pl:contains("IMDb")');
if (imdb_anchor && imdb_anchor.length > 0) {
let imdbId = imdb_anchor[0].nextSibling.nodeValue.trim();
if (imdbId) {
videoInfo.imdbId = imdbId;
videoInfo.imdbUrl = Urls.ImdbVideoInfoPageUrl.replace('{imdbId}', imdbId);
self.SearchImdbRating(imdbId);
}
}
resolve(videoInfo);
} catch (e) {
Logger.log('解析失败', ldJsonDb[0].innerText, e)
}
}
}
} else {
Logger.warn(response.statusText);
}
resolve(null);
}
});
});
},
// 查询imdb评分 直接替换dom 不是太好的解决方案
SearchImdbRating: function (imdbId) {
GM_xmlhttpRequest({
method: "GET",
url: Urls.ImdbVideoInfoPageUrl.replace('{imdbId}', imdbId),
onload: function (response) {
if (response.status == 200) {
let imdbHtmlDoc = Utils.ParseDomFromString(response.responseText);
let ldJsonImdb = $(imdbHtmlDoc).find('head > script[type="application/ld+json"]');
if (ldJsonImdb && ldJsonImdb.length > 0 && ldJsonImdb[0].innerText) {
let select = Utils.StringFormat('.videoInfo{0} #imdbScore{0}_' + imdbId, randomCode);
let imdbDom = $(select);
try {
let imdbInfo = JSON.parse(ldJsonImdb[0].innerText.replace(/\r\n/g, '').replace(/\n/g, ''));
let imdbScore = '';
let imdbRatingCount = '';
if (imdbInfo && imdbInfo.aggregateRating) {
let imdbRating = imdbInfo.aggregateRating.ratingValue;
//imdbRatingCount = imdbInfo.aggregateRating.ratingCount || 0;
imdbRatingCount = imdbInfo.aggregateRating.ratingCount || '';
imdbScore = imdbRating ? imdbRating.toFixed(1) : '';
}
// 替换评分
if (imdbDom) {
if (imdbScore) {
//imdbDom.removeClass(Utils.StringFormat('loading{0}', randomCode));
imdbDom.html(imdbScore);
//imdbDom.html(imdbScore + " " + imdbRatingCount);
//imdbDom.parents('a').attr('title', `${imdbRatingCount}`);
imdbDom.next().html("(" + imdbRatingCount + ")");
//console.log(imdbDom.next().text());
}
}
} catch (e) {
Logger.log('解析失败', ldJsonImdb[0].innerText, e);
if (imdbDom) {
imdbDom.parents('a').remove();
}
}
}
}
}
})
}
};
//豆瓣搜索引擎2 使用api 接口评分不太准确 有imdb评分
const DoubanSearchByApi = {
code: "db2",
codeText: "豆瓣2",
SearchVideoList: function (title) {
return new Promise((resolve, reject) => {
if (!title) {
return resolve([]);
}
GM_xmlhttpRequest({
method: "GET",
url: Urls.DbVideoSearchApiUrl.replace('{title}', encodeURIComponent(title)),
onload: function (response) {
let videoList = [];
if (response.status == 200) {
let responseText = response.responseText;
let fmtText = responseText.replace(/\r\n/g, '').replace(/\n/g, '').replace(/\\/g, '');
let match = fmtText.match(/{"items":(.*?),"total":(\d+),"limit":(\d+),"more":(.*?)}/);
if (match && match[1]) {
let htmlDoc = Utils.ParseDomFromString(match[1]);
videoList = Utils.ParseVideoListDom(htmlDoc, '.result');
}
} else {
Logger.warn(response.statusText);
}
resolve(videoList);
}
});
})
},
SearchVideoInfo: function (subjectId) {
return new Promise((resolve, reject) => {
if (!subjectId) {
resolve(null);
}
let url = Urls.DbImdbApiUrl.replace('{subjectId}', subjectId);
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function (response) {
if (response.status == 200) {
let doubanInfo = JSON.parse(response.responseText);
if (doubanInfo && doubanInfo.data) {
let data = doubanInfo.data[0];
let videoInfo = {
title: data.name,
image: data.poster,
url: Urls.DbVideoInfoPageUrl.replace('{subjectId}', doubanInfo.doubanId),
//description: data.description.slice(0, 100) + "…",
description: data.description,
director: Utils.FmtDbPerson(doubanInfo.director, 2),
actor: Utils.FmtDbPerson(doubanInfo.actor, 6),
score: doubanInfo.doubanRating,
ratingCount: doubanInfo.doubanVotes,
imdbScore: doubanInfo.imdbRating,
imdbRatingCount: doubanInfo.imdbVotes,
imdbUrl: Urls.ImdbVideoInfoPageUrl.replace('{imdbId}', doubanInfo.imdbId),
genre: data.genre,
time: Utils.DateFormat(new Date(doubanInfo.dateReleased), "yyyy-MM-dd"),
}
resolve(videoInfo);
}
} else {
Logger.warn(response.statusText);
}
resolve(null);
}
});
});
},
};
// 豆瓣读书搜索引擎1 爬虫模式
const DoubanBookSearchByDom = {
code: "db",
codeText: "豆瓣",
SearchBookList: function (title) {
return new Promise((resolve, reject) => {
if (!title) {
resolve([]);
}
GM_xmlhttpRequest({
method: "GET",
url: Urls.DbBookSearchResultPageUrl.replace('{title}', encodeURIComponent(title)),
onload: function (response) {
let bookList = [];
if (response.status == 200) {
let htmlDoc = Utils.ParseDomFromString(response.responseText);
bookList = Utils.ParseVideoListDom(htmlDoc, '.result-list .result');
} else {
Logger.warn('查询失败,title:' + title, response.statusText);
}
resolve(bookList);
}
});
})
},
SearchBookInfo: function (subjectId) {
let self = this;
return new Promise((resolve, reject) => {
if (!subjectId) {
resolve(null);
}
let url = Urls.DbBookInfoPageUrl.replace('{subjectId}', subjectId);
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function (response) {
if (response.status == 200) {
let doubanInfo = {};
let htmlDoc = Utils.ParseDomFromString(response.responseText);
if (htmlDoc) {
let ldJsonDb = $(htmlDoc).find('script[type="application/ld+json"]');
let ldJsonDbImg = $(htmlDoc).find('meta[property="og:image"]');
let ldJsonDbScri = $(htmlDoc).find('meta[property="og:description"]');
let ldJsonDbAuth = $(htmlDoc).find('meta[property="book:author"]');
let ldJsonDbOthers = $(htmlDoc).find('meta[name="keywords"]');
let ldJsonDbScore = $(htmlDoc).find('strong[property="v:average"]');
let ldJsonDbCount = $(htmlDoc).find('span[property="v:votes"]');
if (ldJsonDb && ldJsonDb.length > 0) {
try {
doubanInfo = JSON.parse(ldJsonDb[0].innerText.replace(/\r\n/g, '').replace(/\n/g, ''));
let bookInfo = {
title: doubanInfo.name,
image: Urls.ImgHandleUrl.replace('{url}', encodeURIComponent(ldJsonDbImg[0].content)),
url: doubanInfo.url,
//description: ldJsonDbScri[0].content.slice(0, 100) + "…",
description: ldJsonDbScri[0].content,
author: ldJsonDbAuth[0].content,
score: ldJsonDbScore[0].innerText,
ratingCount: ldJsonDbCount[0].innerText,
//genre: doubanInfo.genre.join(' / '),
publisher: ldJsonDbOthers[0].content.split(',简介')[0].split(',')[ldJsonDbOthers[0].content.split(',简介')[0].split(',').length-2].split(',')[0],
orignal: '',
translator: '',
time: ldJsonDbOthers[0].content.split(',简介')[0].split(',')[ldJsonDbOthers[0].content.split(',简介')[0].split(',').length-1],
}
resolve(bookInfo);
} catch (e) {
Logger.log('解析失败', ldJsonDb[0].innerText, e)
}
}
}
} else {
Logger.warn(response.statusText);
}
resolve(null);
}
});
});
},
};
const SearchMovie = {
searchEngineList: {}, // 搜索引擎实例列表
searchEngine: "", // 当前搜索引擎。 db:豆瓣
searchEngineObj: {}, // 当前搜索引擎实例
searchText: "", // 被搜索内容
searchVideoList: [], // 当前搜索视频列表
searchVideoInfo: null, // 当前搜索视频内容
searchSelectTitle: '', // 列表选中的视频标题
Execute: function (h_onloadfn) {
this.ResetSearchResult();
let title = this.searchText;
this.searchEngineObj.SearchVideoList(title).then((videoList) => {
this.searchVideoList = videoList;
if (SettingOptions.searchPattern == 'automatic') {
if (videoList && videoList.length > 0) {
let subjectId = videoList[0].subjectId
// 如果在列表中选择过视频,切换引擎后重新选中该视频
if (this.searchSelectTitle) {
try {
videoList.forEach((v, i) => {
if (v && v.title == this.searchSelectTitle) {
subjectId = v.subjectId;
throw new Error('EndForEach');
}
})
} catch (e) {
if (e.message != 'EndForEach') {
Logger.error(e);
}
}
}
this.searchEngineObj.SearchVideoInfo(subjectId).then((result) => {
this.searchVideoInfo = result;
h_onloadfn();
});
} else {
h_onloadfn();
}
} else if (SettingOptions.searchPattern == 'manual') {
h_onloadfn();
}
});
},
UpdateVideoInfo: function (subjectId, h_onloadfn) {
this.searchVideoInfo = null;
this.searchEngineObj.SearchVideoInfo(subjectId).then((result) => {
this.searchVideoInfo = result;
h_onloadfn();
})
},
Update: function () {
this.ResetSearchResult();
this.searchEngineObj = this.searchEngineList[this.searchEngine];
},
Clear: function () {
this.searchEngine = "";
this.searchText = "";
this.searchVideoList = [];
this.searchVideoInfo = null;
},
ResetSearchResult: function () {
this.searchVideoInfo = null;
this.searchVideoList = [];
},
//注册搜索引擎接口并执行搜索引擎的初始化接口
RegisterEngine: function () {
/**
* 搜索引擎必须提供以下接口
code:"", // 代号
codeText:"", // 代号描述
SearchVideoList: function (title) {}, // 返回视频列表
SearchVideoInfo: function (subjectId) {}, // 返回视频信息
init:function(){}, // 可选,初始化接口,在脚本创建时立即执行
*/
const searchEngineListObj = {};
searchEngineListObj[DoubanMovieSearchByDom.code] = DoubanMovieSearchByDom;
searchEngineListObj[DoubanSearchByApi.code] = DoubanSearchByApi;
this.searchEngineList = searchEngineListObj;
for (let key in this.searchEngineList) {
if (this.searchEngineList.hasOwnProperty(key) && this.searchEngineList[key].hasOwnProperty("init")) {
this.searchEngineList[key].init();
}
}
}
};
const SearchBook = {
searchEngineList: {}, // 搜索引擎实例列表
searchEngine: "", // 当前搜索引擎。 db:豆瓣
searchEngineObj: {}, // 当前搜索引擎实例
searchText: "", // 被搜索内容
searchBookList: [], // 当前搜索视频列表
searchBookInfo: null, // 当前搜索视频内容
searchSelectTitle: '', // 列表选中的视频标题
Execute: function (h_onloadfn) {
this.ResetSearchResult();
let title = this.searchText;
this.searchEngineObj.SearchBookList(title).then((bookList) => {
this.searchBookList = bookList;
if (SettingOptions.searchPattern == 'automatic') {
if (bookList && bookList.length > 0) {
let subjectId = bookList[0].subjectId
// 如果在列表中选择过视频,切换引擎后重新选中该视频
if (this.searchSelectTitle) {
try {
bookList.forEach((v, i) => {
if (v && v.title == this.searchSelectTitle) {
subjectId = v.subjectId;
throw new Error('EndForEach');
}
})
} catch (e) {
if (e.message != 'EndForEach') {
Logger.error(e);
}
}
}
this.searchEngineObj.SearchBookInfo(subjectId).then((result) => {
this.searchBookInfo = result;
h_onloadfn();
});
} else {
h_onloadfn();
}
} else if (SettingOptions.searchPattern == 'manual') {
h_onloadfn();
}
});
},
UpdateBookInfo: function (subjectId, h_onloadfn) {
this.searchBookInfo = null;
this.searchEngineObj.SearchBookInfo(subjectId).then((result) => {
this.searchBookInfo = result;
h_onloadfn();
})
},
Update: function () {
this.ResetSearchResult();
this.searchEngineObj = this.searchEngineList[this.searchEngine];
},
Clear: function () {
this.searchEngine = "";
this.searchText = "";
this.searchBookList = [];
this.searchBookInfo = null;
},
ResetSearchResult: function () {
this.searchBookInfo = null;
this.searchBookList = [];
},
//注册搜索引擎接口并执行搜索引擎的初始化接口
RegisterEngine: function () {
/**
* 搜索引擎必须提供以下接口
code:"", // 代号
codeText:"", // 代号描述
SearchVideoList: function (title) {}, // 返回视频列表
SearchVideoInfo: function (subjectId) {}, // 返回视频信息
init:function(){}, // 可选,初始化接口,在脚本创建时立即执行
*/
const searchEngineListObj = {};
searchEngineListObj[DoubanBookSearchByDom.code] = DoubanBookSearchByDom;
this.searchEngineList = searchEngineListObj;
for (let key in this.searchEngineList) {
if (this.searchEngineList.hasOwnProperty(key) && this.searchEngineList[key].hasOwnProperty("init")) {
this.searchEngineList[key].init();
}
}
}
};
// 面板
const Panel = {
popBoxEl: {},
Create: function (title, placement, isShowArrow, content, shownFn) {
let self = this;
$(self.popBoxEl).jPopBox({
title: title,
className: 'JPopBox-tip-white',
placement: placement,
trigger: 'none',
isTipHover: true,
isShowArrow: isShowArrow,
content: function () {
return Utils.StringFormat('<div id="panelBody{0}">{1}</div>', randomCode, content);
}
});
$(self.popBoxEl).on("shown.jPopBox", function () {
let $panel = $("div.JPopBox-tip-white");
typeof shownFn === 'function' && shownFn($panel);
});
$(self.popBoxEl).jPopBox('show');
},
Update: function (Fn) {
let $panel = $("div.JPopBox-tip-white");
Fn($panel);
},
Destroy: function () {
$(this.popBoxEl).jPopBox("destroy");
},
CreateStyle: function () {
let s = "";
s += Utils.StringFormat("#panelBody{0}>div input,#panelBody{0}>div select{padding:3px;margin:0;background:#fff;font-size:14px;border:1px solid #a9a9a9;color:black;width:auto;height:25px;display:inline-block;position: static;}#panelBody{0} a{text-decoration:none;border-bottom:0;color:#494949}", randomCode);
s += Utils.StringFormat("#panelBody{0} .head{0}{display:flex;align-items:center;height:30px}#panelBody{0} .logo{0}{width:75px;margin:0;vertical-align:bottom}#panelBody{0} .text{0}{margin:10px 0 0 10px;color:#388e8e;font-size:10px;cursor:pointer;opacity:0.6}#panelBody{0} .listBtn{0}{margin:10px 0 0 1px;color:#999;font-size:10px;cursor:pointer}", randomCode);
s += Utils.StringFormat("#panelBody{0} .content{0} .noData{0}{margin:30px 40%}#panelBody{0} .content{0} .loading{0}{border:5px solid #f3f3f3;border-radius:50%;border-top:5px solid #3498db;width:30px;height:30px;animation:db_search_turn{0} 2s linear infinite;margin:20px;margin-left:45%}", randomCode);
//s += Utils.StringFormat("#panelBody{0} .score{0}{position:absolute;top:5px;right:5px;display:flex;align-items:center;column-gap:10px}#panelBody{0} .score{0}>a{display:flex;align-items:center}#panelBody{0} .score{0} svg{background:0}#panelBody{0} .score{0} span{font-size:30px}#panelBody{0} .score{0} span.loading{0}{border:3px solid #f3f3f3;border-radius:50%;border-top:3px solid #3498db;width:20px;height:20px;animation:db_search_turn{0} 2s linear infinite;margin:5px;display:inline-block}", randomCode);
s += Utils.StringFormat("#panelBody{0} .info{0} .title{0}{font-size:18px;font-weight:bold;margin:5px 0}#panelBody{0} .score{0}{position:absolute;right:15px;display:flex;align-items:center;column-gap:5px}#panelBody{0} .score{0}>a{display:flex;align-items:center}#panelBody{0} .score{0} svg{background:0;padding-bottom:1px;padding-right:3px}#panelBody{0} .score{0} .iscore{0}{font-size:18px}#panelBody{0} .score{0} .count{0}{font-size:8px;padding-top:3px;padding-left:2px;}#panelBody{0} .score{0} span.loading{0}{border:3px solid #f3f3f3;border-radius:50%;border-top:3px solid #3498db;width:20px;height:20px;animation:db_search_turn{0} 2s linear infinite;margin:5px;display:inline-block}#panelBody{0} .info{0} .left{0}{float:left;margin:3px 5px 0 0;display:block;position:relative;width:120px;height:168px;background-repeat:no-repeat;background-position:50%;background-image:url({1});background-size:100%}#panelBody{0} .info{0} .left{0}>img{width:120px;height:168px}#panelBody{0} .info{0} .right{0}{min-height:175px;padding-left:132px}#panelBody{0} .info{0} .right{0} .item{0}>span{color:#666}", randomCode, Images.VideoDefaultImg);
//s += Utils.StringFormat("#panelBody{0} .list{0}{overflow:auto;height:200px;margin-top:5px}#panelBody{0} .list{0}::-webkit-scrollbar{display:none}#panelBody{0} .list{0} .listItem{0}{margin-top:5px;height:70px;position:relative}#panelBody{0} .listItem{0} .left{0}{float:left;margin-right:5px;display:block;position:relative;width:48px;height:68px;background-repeat:no-repeat;background-position:50%;background-image:url({1});background-size:100%}#panelBody{0} .listItem{0} .left{0}>img{width:48px;height:68px}#panelBody{0} .listItem{0} .right{0} .title{0}{width:320px;font-size:18px;margin-bottom:9px;font-weight:bold;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;word-break:break-all}#panelBody{0} .listItem{0} .right{0} .score{0}{position:absolute;right:5px;top:0;font-size:25px}#panelBody{0} .listItem{0} .right{0} .info{0}{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;word-break:break-all;font-size:12px;border:0}", randomCode, Images.VideoDefaultImg);
s += Utils.StringFormat("#panelBody{0} .list{0}{overflow:auto;height:200px;margin-top:5px}#panelBody{0} .list{0}::-webkit-scrollbar{display:none}#panelBody{0} .list{0} .listItem{0}{margin-top:5px;height:70px;position:relative;padding-top:5px;padding-bottom:5px;}#panelBody{0} .listItem{0} .left{0}{float:left;margin-right:5px;display:block;position:relative;width:48px;height:68px;background-repeat:no-repeat;background-position:50%;background-image:url({1});background-size:100%}#panelBody{0} .listItem{0} .left{0}>img{width:48px;height:68px}#panelBody{0} .listItem{0} .right{0}{padding-left:60px}#panelBody{0} .listItem{0} .right{0} .title{0}{width:320px;font-size:13px;margin-bottom:9px;/*font-weight:bold;*/white-space:nowrap;text-overflow:ellipsis;overflow:hidden;word-break:break-all;color:#3377aa}#panelBody{0} .listItem{0} .right{0} .score{0}{position:absolute;right:5px;top:0px;padding-top:5px;font-size:13px;color:#e09015}#panelBody{0} .listItem{0} .right{0} .info{0}{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;word-break:break-all;font-size:12px;border:0;color:#9d9d9d}", randomCode, Images.VideoDefaultImg);
return s;
}
};
// 电影搜索面板
const MovieSearchPanel = {
Create: function (popBoxEl) {
var text = window.getSelection().toString().trim();
let self = this;
let searchEngineOptionsHtml = "";
for (let k in SearchMovie.searchEngineList) {
if (SearchMovie.searchEngineList.hasOwnProperty(k)) {
let v = SearchMovie.searchEngineList[k].codeText;
let selectOption = "";
if (SearchMovie.searchEngine == k) {
selectOption = 'selected="selected"';
}
searchEngineOptionsHtml += Utils.StringFormat('<option value="{0}" {2}>{1}</option>', k, v, selectOption);
}
}
let wordSearchPanelHtml = '';
//let headHtml = Utils.StringFormat(`<div class="head{0}"><a href="" class="link22" target="_blank"><img class="logo{0}" src="" title="" /></a><select class="select22">{1}</select><div id="showSearchList_{0}" class="listBtn{0}">展示搜索列表</div></div>`, randomCode, searchEngineOptionsHtml);
//let headHtml = Utils.StringFormat(`<div class="head{0}"><a href="${Urls.MovieSearchResultPageUrl.replace('{title}', encodeURIComponent(text))}" class="link22" target="_blank"><img id="doubanLogo_{0}" class="logo{0}" src="${Images.MovieIconBase64}" title="豆瓣电影" /></a><div id="showSearchText_{0}" class="text{0}">${text}</div><div id="showSearchList_{0}" class="listBtn{0}">展示搜索列表</div></div>`, randomCode, searchEngineOptionsHtml);
let headHtml = Utils.StringFormat(`<div class="head{0}"><img id="doubanLogo_{0}" class="logo{0}" src="${Images.MovieIconBase64}" title="豆瓣电影" /><div id="showSearchText_{0}" class="text{0}">${text}</div><div id="showSearchList_{0}" class="listBtn{0}">展示搜索列表</div></div>`, randomCode, searchEngineOptionsHtml);
wordSearchPanelHtml += headHtml;
wordSearchPanelHtml += Utils.StringFormat('<div class="content{0}">', randomCode);
if (SettingOptions.searchPattern == 'automatic') {
wordSearchPanelHtml += self.GetVideoInfoHtml();
} else if (SettingOptions.searchPattern == 'manual') {
wordSearchPanelHtml += self.GetVideoListHtml();
}
wordSearchPanelHtml += '</div>';
Panel.popBoxEl = popBoxEl;
Panel.Create("", "auto bottom", false, wordSearchPanelHtml, function ($panel) {
//设置搜索结果面板鼠标位置
/*if(ev.pageX < 945) {
$panel.css({
left: ev.pageX + 'px',
top: ev.pageY + 12 + 'px'
});
} else {
$panel.css({
left: 945 + 'px',
top: ev.pageY + 12 + 'px'
});
}*/
if(ev.pageX < 945 && ev.clientY < 485) {
$panel.css({
left: ev.pageX + 'px',
top: ev.pageY + 12 + 'px'
});
} else if(ev.pageX < 945 && ev.clientY > 485) {
$panel.css({
left: ev.pageX + 'px',
top: 750 - 255 + document.documentElement.scrollTop + 'px'
});
} else if(ev.pageX > 945 && ev.clientY < 485) {
$panel.css({
left: 945 + 'px',
top: ev.pageY + 12 + 'px'
});
} else if(ev.pageX > 945 && ev.clientY > 485) {
$panel.css({
left: 945 + 'px',
top: 750 - 255 + document.documentElement.scrollTop + 'px'
});
/*} else {
$panel.css({
left: 945 + 'px',
top: ev.pageY + 12 + 'px'
});*/
}
// 搜索引擎
$panel.find(Utils.StringFormat("#panelBody{0} div:eq(0) select:eq(0)", randomCode)).change(function (e) {
SearchMovie.searchEngine = $(this).find("option:selected").val();
self.Loading($panel);
SearchMovie.Update();
SearchMovie.Execute(function () {
if (SettingOptions.searchPattern == 'automatic') {
self.Update();
} else if (SettingOptions.searchPattern == 'manual') {
self.ShowSearchList();
}
});
});
// 搜索列表
$panel.find(Utils.StringFormat("#panelBody{0} #showSearchList_{0}", randomCode)).click(function (e) {
self.ShowSearchList();
});
$panel.find(Utils.StringFormat("#panelBody{0} .logo{0}", randomCode)).click(function () {
GM_openInTab(Urls.MovieSearchResultPageUrl.replace('{title}', encodeURIComponent(text)), {
active: false
});
//console.log("ok")
});
if (SettingOptions.searchPattern == 'manual') {
// 列表点击事件
$panel.find(Utils.StringFormat("#panelBody{0} .listItem{0}", randomCode)).click(function () {
let subjectId = $(this).attr('data-id');
SearchMovie.searchSelectTitle = $(this).attr('data-name');
self.Loading($panel);
SearchMovie.UpdateVideoInfo(subjectId, function () {
self.Update();
});
$(Utils.StringFormat("#panelBody{0} #doubanLogo_{0}", randomCode)).hide();//logo隐藏
$(Utils.StringFormat("#panelBody{0} #showSearchText_{0}", randomCode)).hide();//划词隐藏
});
}
if (SettingOptions.searchPattern == 'manual' || !SearchMovie.searchVideoList || SearchMovie.searchVideoList.length == 0) {
$(Utils.StringFormat("#panelBody{0} #showSearchList_{0}", randomCode)).hide();
}
});
},
Update: function () {
let self = this;
Panel.Update(function ($panel) {
let html = self.GetVideoInfoHtml();
$panel.find(Utils.StringFormat("#panelBody{0} .content{0}", randomCode)).html("").html(html);
});
if (SearchMovie.searchVideoList && SearchMovie.searchVideoList.length > 0) {
$(Utils.StringFormat("#panelBody{0} #showSearchList_{0}", randomCode)).css("display", "inline");
$(Utils.StringFormat("#panelBody{0} #doubanLogo_{0}", randomCode)).css("display", "none");//logo隐藏
$(Utils.StringFormat("#panelBody{0} #showSearchText_{0}", randomCode)).css("display", "none");//划词隐藏
}
//点title后台打开电影读书页面
//console.log(self.GetUrl())
var url = self.GetUrl();
let $panel = $("div.JPopBox-tip-white");
$panel.find(Utils.StringFormat("#panelBody{0} .title{0}", randomCode)).click(function () {
GM_openInTab(url, {
active: false
});
//console.log("ok")
});
$panel.find(Utils.StringFormat("#panelBody{0} .left{0}", randomCode)).click(function () {
GM_openInTab(url, {
active: false
});
//console.log("ok")
});
},
ShowSearchList: function () {
let self = this;
let html = self.GetVideoListHtml();
let $panel = $("div.JPopBox-tip-white");
$panel.find(Utils.StringFormat("#panelBody{0} .content{0}", randomCode)).html("").html(html);
$panel.find(Utils.StringFormat("#panelBody{0} .listItem{0}", randomCode)).click(function () {
let subjectId = $(this).attr('data-id');
SearchMovie.searchSelectTitle = $(this).attr('data-name');
self.Loading($panel);
SearchMovie.UpdateVideoInfo(subjectId, function () {
self.Update();
});
});
$(Utils.StringFormat("#panelBody{0} #showSearchList_{0}", randomCode)).hide();
$(Utils.StringFormat("#panelBody{0} #doubanLogo_{0}", randomCode)).css("display", "inline");//列表logo显示
$(Utils.StringFormat("#panelBody{0} #showSearchText_{0}", randomCode)).css("display", "inline");//列表划词显示
},
GetVideoListHtml: function () {
let htmlArr = [];
let videoList = SearchMovie.searchVideoList;
if (videoList && videoList.length > 0) {
let itemTemplate = `
<div class="listItem{0}" data-id="{4}" data-name="{2}">
<div class="left{0}"><img src="{1}" onerror="javascript:this.src='${Images.VideoDefaultImg}'"></div>
<div class="right{0}">
<div class="title{0}">{2}</div>
<div class="score{0}" title="{7}">{3}</div>
<div class="info{0}">{6}</div>
<div class="info{0}">{5}</div>
</div>
</div>`;
htmlArr.push(Utils.StringFormat('<div class="list{0}">', randomCode));
videoList.forEach((item) => {
let videoItem = Utils.StringFormat(itemTemplate, randomCode, item.image, item.title, item.score, item.subjectId, item.description, item.cast, item.ratingCount);
htmlArr.push(videoItem);
})
htmlArr.push('</div>');
} else {
htmlArr.push(Utils.StringFormat('<div class="noData{0}">未搜索到内容</div>', randomCode));
}
return htmlArr.join('');
},
GetVideoInfoHtml: function () {
let videoInfoHtml = '';
let videoInfo = SearchMovie.searchVideoInfo;
if (videoInfo) {
let templateArr = [];
templateArr.push('<div class="videoInfo{0}">');
if (videoInfo.score || videoInfo.imdbScore || videoInfo.imdbId) { // 评分
templateArr.push('<div class="score{0}">');
if (videoInfo.score) {
//templateArr.push(`<a href="{3}" target="_blank" title="{13} 人参与评分">${Images.DbSvg}<span>{5}</span></a>`);
//templateArr.push(`<a href="{3}" target="_blank" title="">${Images.DbSvg}<span>{5}</span></a>`);
templateArr.push(`<a href="{3}" target="_blank" class="link22" title="">${Images.DbSvg}<span class="iscore{0}">{5}</span><span class="count{0}">({13})</span></a>`);
//templateArr.push(`<a href="javascript:;" onclick="widnow.open(\'{3}\')" class="link22" title="{13} 人参与评分">${Images.DbSvg}<span class="score22">{5}</span></a>`);
//templateArr.push(`<a href="javascript:GM_openInTab(\'{3}\', {active: false})" class="link22" title="{13} 人参与评分">${Images.DbSvg}<span class="score22">{5}</span></a>`);
}
if (videoInfo.imdbScore || videoInfo.imdbId) { // imdb 有评分直接展示 没有评分有id的情况展示loading 豆瓣2不会传imdbId 用来区分
/*templateArr.push(`<a href="{11}" target="_blank" class="link22" title="{14} 人参与评分">${Images.ImdbSvg}
<span class="score22" id="imdbScore{0}_{12}">{10}</span>
</a>`);*/
/*templateArr.push(`<a href="{11}" target="_blank" class="link22" title="">${Images.ImdbSvg}
<span class="score22" id="imdbScore{0}_{12}">{10}</span>
</a>`);*/
templateArr.push(`<a href="{11}" target="_blank" class="link22" title="">${Images.ImdbSvg}
<span class="iscore{0}" id="imdbScore{0}_{12}">{10}</span>
<span class="count{0}">{14}</span>
</a>`);
/*templateArr.push(`<a href="javascript:;" onclick="window.open(\'{3}\'')" class="link22" title="{14} 人参与评分">${Images.ImdbSvg}
<span class="${videoInfo.imdbScore ? 'score22' : 'loading{0}'}" id="imdbScore{0}_{12}">{10}</span>
</a>`); */
/*templateArr.push(`<a href="javascript:GM_openInTab(\'{3}\', {active: false})" class="link22" title="{14} 人参与评分">${Images.ImdbSvg}
<span class="score22" id="imdbScore{0}_{12}">{10}</span>
</a>`); */
}
templateArr.push('</div>');
}
templateArr.push(`
<div class="info{0}">
<!--<div class="title{0}"><a href="{3}" class="link22" target="_blank">{1}</a></div>-->
<!--<div class="title{0}"><a href="" target="_blank">{1}</a></div>-->
<div class="title{0}">{1}</div>
<div class="left{0}"><img src="{2}" onerror="javascript:this.src='${Images.VideoDefaultImg}'"/></div>
<div class="right{0}">`);
/*templateArr.push(`
<div class="info{0}">
<div class="title{0}"><a href="javascript:;" onclick="openlink(\'{3}\')" class="link22" target="_blank">{1}</a></div>
<div class="left{0}"><img src="{2}" onerror="javascript:this.src='${Images.VideoDefaultImg}'"/></div>
<div class="right{0}">`);*/
if (videoInfo.director) {
templateArr.push('<div class="item{0}"><span class="item22">导演</span>:{9}</div>');
}
if (videoInfo.actor) {
templateArr.push('<div class="item{0}"><span class="item22">主演</span>:{8}</div>');
}
if (videoInfo.genre) {
templateArr.push('<div class="item{0}"><span class="item22">类型</span>:{7}</div>');
}
if (videoInfo.time) {
templateArr.push('<div class="item{0}"><span class="item22">时间</span>:{6}</div>');
}
if (videoInfo.description) {
templateArr.push('<div class="item{0}"><span class="item22">简介</span>:{4}</div>');
}
templateArr.push(`</div></div>`);
/*videoInfoHtml = Utils.StringFormat(templateArr.join(''), randomCode,
videoInfo.title.slice(0, 35), videoInfo.image, videoInfo.url, videoInfo.description,
videoInfo.score, videoInfo.time, videoInfo.genre, videoInfo.actor, videoInfo.director,
videoInfo.imdbScore || '', videoInfo.imdbUrl, videoInfo.imdbId || 0,
videoInfo.ratingCount || 0, videoInfo.imdbRatingCount || 0);*/
videoInfoHtml = Utils.StringFormat(templateArr.join(''), randomCode,
videoInfo.title, videoInfo.image, videoInfo.url, videoInfo.description,
videoInfo.score, videoInfo.time, videoInfo.genre, videoInfo.actor, videoInfo.director,
videoInfo.imdbScore || '', videoInfo.imdbUrl, videoInfo.imdbId || 0,
videoInfo.ratingCount || 0, videoInfo.imdbRatingCount || '');
} else {
videoInfoHtml = Utils.StringFormat('<div class="noData{0}">未搜索到内容</div>', randomCode);
}
return videoInfoHtml;
},
Loading: function (panel) {
panel.find(Utils.StringFormat("#panelBody{0} .content{0}", randomCode)).html("").html(Utils.StringFormat('<div class="loading{0}"></div>', randomCode));
},
GetUrl: function () { //返回电影读书页面
let videoInfo = SearchMovie.searchVideoInfo;
var url = videoInfo.url;
return url;
}
};
// 读书搜索面板
const BookSearchPanel = {
Create: function (popBoxEl) {
var text = window.getSelection().toString().trim();
let self = this;
let searchEngineOptionsHtml = "";
for (let k in SearchBook.searchEngineList) {
if (SearchBook.searchEngineList.hasOwnProperty(k)) {
let v = SearchBook.searchEngineList[k].codeText;
let selectOption = "";
if (SearchBook.searchEngine == k) {
selectOption = 'selected="selected"';
}
searchEngineOptionsHtml += Utils.StringFormat('<option value="{0}" {2}>{1}</option>', k, v, selectOption);
}
}
let wordSearchPanelHtml = '';
//let headHtml = Utils.StringFormat(`<div class="head{0}"><a href="" class="link22" target="_blank"><img class="logo{0}" src="" title="" /></a><select class="select22">{1}</select><div id="showSearchList_{0}" class="listBtn{0}">展示搜索列表</div></div>`, randomCode, searchEngineOptionsHtml);
//let headHtml = Utils.StringFormat(`<div class="head{0}"><a href="${Urls.BookSearchResultPageUrl.replace('{title}', encodeURIComponent(text))}" class="link22" target="_blank"><img id="doubanLogo_{0}" class="logo{0}" src="${Images.BookIconBase64}" title="豆瓣读书" /></a><div id="showSearchText_{0}" class="text{0}">${text}</div><div id="showSearchList_{0}" class="listBtn{0}">展示搜索列表</div></div>`, randomCode, searchEngineOptionsHtml);
let headHtml = Utils.StringFormat(`<div class="head{0}"><img id="doubanLogo_{0}" class="logo{0}" src="${Images.BookIconBase64}" title="豆瓣读书" /><div id="showSearchText_{0}" class="text{0}">${text}</div><div id="showSearchList_{0}" class="listBtn{0}">展示搜索列表</div></div>`, randomCode, searchEngineOptionsHtml);
wordSearchPanelHtml += headHtml;
wordSearchPanelHtml += Utils.StringFormat('<div class="content{0}">', randomCode);
if (SettingOptions.searchPattern == 'automatic') {
wordSearchPanelHtml += self.GetBookInfoHtml();
} else if (SettingOptions.searchPattern == 'manual') {
wordSearchPanelHtml += self.GetBookListHtml();
}
wordSearchPanelHtml += '</div>';
Panel.popBoxEl = popBoxEl;
Panel.Create("", "auto bottom", false, wordSearchPanelHtml, function ($panel) {
/*if(ev.pageX < 945) {
$panel.css({
left: ev.pageX + 'px',
top: ev.pageY + 12 + 'px'
});
} else {
$panel.css({
left: 945 + 'px',
top: ev.pageY + 12 + 'px'
});
}*/
if(ev.pageX < 945 && ev.clientY < 485) {
$panel.css({
left: ev.pageX + 'px',
top: ev.pageY + 12 + 'px'
});
} else if(ev.pageX < 945 && ev.clientY > 485) {
$panel.css({
left: ev.pageX + 'px',
top: 750 - 255 + document.documentElement.scrollTop + 'px'
});
} else if(ev.pageX > 945 && ev.clientY < 485) {
$panel.css({
left: 945 + 'px',
top: ev.pageY + 12 + 'px'
});
} else if(ev.pageX > 945 && ev.clientY > 485) {
$panel.css({
left: 945 + 'px',
top: 750 - 255 + document.documentElement.scrollTop + 'px'
});
/*} else {
$panel.css({
left: 945 + 'px',
top: ev.pageY + 12 + 'px'
});*/
}
// 搜索引擎
$panel.find(Utils.StringFormat("#panelBody{0} div:eq(0) select:eq(0)", randomCode)).change(function (e) {
SearchBook.searchEngine = $(this).find("option:selected").val();
self.Loading($panel);
SearchBook.Update();
SearchBook.Execute(function () {
if (SettingOptions.searchPattern == 'automatic') {
self.Update();
} else if (SettingOptions.searchPattern == 'manual') {
self.ShowSearchList();
}
});
});
// 搜索列表
$panel.find(Utils.StringFormat("#panelBody{0} #showSearchList_{0}", randomCode)).click(function (e) {
self.ShowSearchList();
});
$panel.find(Utils.StringFormat("#panelBody{0} .logo{0}", randomCode)).click(function () {
GM_openInTab(Urls.BookSearchResultPageUrl.replace('{title}', encodeURIComponent(text)), {
active: false
});
//console.log("ok")
});
if (SettingOptions.searchPattern == 'manual') {
// 列表点击事件
$panel.find(Utils.StringFormat("#panelBody{0} .listItem{0}", randomCode)).click(function () {
let subjectId = $(this).attr('data-id');
SearchBook.searchSelectTitle = $(this).attr('data-name');
self.Loading($panel);
SearchBook.UpdateBookInfo(subjectId, function () {
self.Update();
});
$(Utils.StringFormat("#panelBody{0} #doubanLogo_{0}", randomCode)).hide();//logo隐藏
$(Utils.StringFormat("#panelBody{0} #showSearchText_{0}", randomCode)).hide();//划词隐藏
});
}
if (SettingOptions.searchPattern == 'manual' || !SearchBook.searchBookList || SearchBook.searchBookList.length == 0) {
$(Utils.StringFormat("#panelBody{0} #showSearchList_{0}", randomCode)).hide();
}
});
},
Update: function () {
let self = this;
Panel.Update(function ($panel) {
let html = self.GetBookInfoHtml();
$panel.find(Utils.StringFormat("#panelBody{0} .content{0}", randomCode)).html("").html(html);
});
if (SearchBook.searchBookList && SearchBook.searchBookList.length > 0) {
$(Utils.StringFormat("#panelBody{0} #showSearchList_{0}", randomCode)).css("display", "inline");
$(Utils.StringFormat("#panelBody{0} #doubanLogo_{0}", randomCode)).css("display", "none");//列表logo显示
$(Utils.StringFormat("#panelBody{0} #showSearchText_{0}", randomCode)).css("display", "none");//列表划词显示
}
//点title后台打开电影读书页面
//console.log(self.GetUrl())
var url = self.GetUrl();
let $panel = $("div.JPopBox-tip-white");
$panel.find(Utils.StringFormat("#panelBody{0} .title{0}", randomCode)).click(function () {
GM_openInTab(url, {
active: false
});
//console.log("ok")
});
$panel.find(Utils.StringFormat("#panelBody{0} .left{0}", randomCode)).click(function () {
GM_openInTab(url, {
active: false
});
//console.log("ok")
});
},
ShowSearchList: function () {
let self = this;
let html = self.GetBookListHtml();
let $panel = $("div.JPopBox-tip-white");
$panel.find(Utils.StringFormat("#panelBody{0} .content{0}", randomCode)).html("").html(html);
$panel.find(Utils.StringFormat("#panelBody{0} .listItem{0}", randomCode)).click(function () {
let subjectId = $(this).attr('data-id');
SearchBook.searchSelectTitle = $(this).attr('data-name');
self.Loading($panel);
SearchBook.UpdateBookInfo(subjectId, function () {
self.Update();
});
});
$(Utils.StringFormat("#panelBody{0} #showSearchList_{0}", randomCode)).hide();
$(Utils.StringFormat("#panelBody{0} #doubanLogo_{0}", randomCode)).css("display", "inline");//列表logo显示
$(Utils.StringFormat("#panelBody{0} #showSearchText_{0}", randomCode)).css("display", "inlinee");//列表划词显示
},
GetBookListHtml: function () {
let htmlArr = [];
let bookList = SearchBook.searchBookList;
if (bookList && bookList.length > 0) {
let itemTemplate = `
<div class="listItem{0}" data-id="{4}" data-name="{2}">
<div class="left{0}"><img src="{1}" onerror="javascript:this.src='${Images.VideoDefaultImg}'"></div>
<div class="right{0}">
<div class="title{0}">{2}</div>
<div class="score{0}" title="{7}">{3}</div>
<div class="info{0}">{6}</div>
<div class="info{0}">{5}</div>
</div>
</div>`;
htmlArr.push(Utils.StringFormat('<div class="list{0}">', randomCode));
bookList.forEach((item) => {
let bookItem = Utils.StringFormat(itemTemplate, randomCode, item.image, item.title, item.score, item.subjectId, item.description, item.cast, item.ratingCount);
htmlArr.push(bookItem);
})
htmlArr.push('</div>');
} else {
htmlArr.push(Utils.StringFormat('<div class="noData{0}">未搜索到内容</div>', randomCode));
}
return htmlArr.join('');
},
GetBookInfoHtml: function () {
let bookInfoHtml = '';
let bookInfo = SearchBook.searchBookInfo;
if (bookInfo) {
let templateArr = [];
templateArr.push('<div class="videoInfo{0}">');
if (bookInfo.score) { // 评分
templateArr.push('<div class="score{0}">');
if (bookInfo.score) {
//templateArr.push(`<a href="{3}" target="_blank" class="link22" title="{11} 人参与评分">${Images.DbSvg}<span class="score22">{6}</span></a>`);
//templateArr.push(`<a href="{3}" target="_blank" class="link22" title="">${Images.DbSvg}<span class="score22">{6}</span></a>`);
templateArr.push(`<a href="{3}" target="_blank" class="link22" title="">${Images.DbSvg}<span class="iscore{0}">{6}</span><span class="count{0}">({11})</span></a>`);
//templateArr.push(`<a href="javascript:;" onclick="GM_openInTab(\'{3}\', loadInBackground)" class="link22" title="{11} 人参与评分">${Images.DbSvg}<span class="score22">{6}</span></a>`);
}
templateArr.push('</div>');
}
templateArr.push(`
<div class="info{0}">
<!--<div class="title{0}"><a href="{3}" class="link22" target="_blank">{1}</a></div>-->
<div class="title{0}">{1}</div>
<div class="left{0}"><img src="{2}" onerror="javascript:this.src='${Images.VideoDefaultImg}'"/></div>
<div class="right{0}">`);
if (bookInfo.author) {
templateArr.push('<div class="item{0}"><span class="item22">作者</span>:{5}</div>');
}
if (bookInfo.publisher) {
templateArr.push('<div class="item{0}"><span class="item22">出版社</span>:{7}</div>');
}
if (bookInfo.orignal) {
templateArr.push('<div class="item{0}"><span class="item22">原作名</span>:{8}</div>');
}
if (bookInfo.time) {
templateArr.push('<div class="item{0}"><span class="item22">出版年</span>:{10}</div>');
}
if (bookInfo.description) {
templateArr.push('<div class="item{0}"><span class="item22">简介</span>:{4}</div>');
}
templateArr.push(`</div></div>`);
/*bookInfoHtml = Utils.StringFormat(templateArr.join(''), randomCode,
bookInfo.title.slice(0, 35), bookInfo.image, bookInfo.url, bookInfo.description,
bookInfo.author, bookInfo.score, bookInfo.publisher, bookInfo.orignal,
bookInfo.translator, bookInfo.time, bookInfo.ratingCount || 0);*/
bookInfoHtml = Utils.StringFormat(templateArr.join(''), randomCode,
bookInfo.title, bookInfo.image, bookInfo.url, bookInfo.description,
bookInfo.author, bookInfo.score, bookInfo.publisher, bookInfo.orignal,
bookInfo.translator, bookInfo.time, bookInfo.ratingCount || '');
} else {
bookInfoHtml = Utils.StringFormat('<div class="noData{0}">未搜索到内容</div>', randomCode);
}
return bookInfoHtml;
},
Loading: function (panel) {
panel.find(Utils.StringFormat("#panelBody{0} .content{0}", randomCode)).html("").html(Utils.StringFormat('<div class="loading{0}"></div>', randomCode));
},
GetUrl: function () { //返回电影读书页面
let bookInfo = SearchBook.searchBookInfo;
var url = bookInfo.url;
return url;
}
};
// 选词 代码来自扩展 uBlock Origin https://github.com/gorhill/uBlock/blob/master/src/js/scriptlets/epicker.js
const DoubanPickerTool = {
sessionId: '',
iframeHost: '',
textFilterCandidates: [],
targetElements: [],
pickerRoot: null,
initDoubanPicker: function (iframeHost) {
if (!iframeHost) { return; }
this.iframeHost = iframeHost;
// 主页面监听message事件,接收子组件的值
let self = this;
window.addEventListener('message', function (e) {
if (e.origin == self.iframeHost) {
self.onDialogMessage(e.data)
}
}, false);
},
getElementBoundingClientRect: function (elem) {
let rect = typeof elem.getBoundingClientRect === 'function' ? elem.getBoundingClientRect() : { height: 0, left: 0, top: 0, width: 0 };
if (rect.width !== 0 && rect.height !== 0) {
return rect;
}
let left = rect.left,
right = rect.right,
top = rect.top,
bottom = rect.bottom;
for (const child of elem.children) {
rect = this.getElementBoundingClientRect(child);
if (rect.width === 0 || rect.height === 0) {
continue;
}
if (rect.left < left) { left = rect.left; }
if (rect.right > right) { right = rect.right; }
if (rect.top < top) { top = rect.top; }
if (rect.bottom > bottom) { bottom = rect.bottom; }
}
return { height: bottom - top, left, top, width: right - left };
},
highlightElements: function (elems, force) {
if (
(force !== true) &&
(elems.length === this.targetElements.length) &&
(elems.length === 0 || elems[0] === this.targetElements[0])
) {
return;
}
this.targetElements = [];
const ow = self.innerWidth;
const oh = self.innerHeight;
const islands = [];
for (const elem of elems) {
if (elem === this.pickerRoot) { continue; }
this.targetElements.push(elem);
const rect = this.getElementBoundingClientRect(elem);
if (
rect.left > ow || rect.top > oh ||
rect.left + rect.width < 0 || rect.top + rect.height < 0
) {
continue;
}
islands.push(
`M${rect.left} ${rect.top}h${rect.width}v${rect.height}h-${rect.width}z`
);
}
this.sendMessageToIframe({
ocean: `M0 0h${ow}v${oh}h-${ow}z`,
islands: islands.join(''),
what: "svgPaths"
});
},
textFilterFromElement: function (elem) {
if (elem === null) { return 0; }
if (elem.nodeType !== 1) { return 0; }
if (elem.nodeName === "HTML" || elem.nodeName === "BODY") { return 0; }
this.textFilterCandidates = this.getNodeText(elem);
return 1;
},
getNodeText: function (elem) {
let temp = []
if (elem) {
const forFn = function (ele) {
if (ele.childNodes.length > 0 && ele.nodeName != 'A') {
let children = Array.from(ele.childNodes);
children.forEach((c) => {
forFn(c);
})
} else {
let text = ele.textContent;
if (ele.nodeName == 'INPUT') {
text = ele.value;
} else if (ele.nodeName == 'A') {
text = ele.innerText;
}
if (text && text.trim()) {
temp.push(text.trim());
}
}
}
forFn(elem);
}
return temp;
},
filtersFrom: function (x, y) {
this.textFilterCandidates.length = 0
let elem = null;
if (typeof x === 'number') {
elem = this.elementFromPoint(x, y);
} else if (x instanceof HTMLElement) {
elem = x;
x = undefined;
}
this.textFilterFromElement(elem);
return this.textFilterCandidates.length;
},
showDialog: function () {
this.sendMessageToIframe({
what: 'showDialog',
text: this.textFilterCandidates
});
},
elementFromPoint: function (x, y) {
let lastX, lastY;
if (x !== undefined) {
lastX = x; lastY = y;
} else if (lastX !== undefined) {
x = lastX; y = lastY;
} else {
return null;
}
if (!this.pickerRoot) { return null; }
this.pickerRoot.style.pointerEvents = 'none';
let elems = document.elementsFromPoint(x, y);
elems = elems.filter(ele => ele.name != 'myFrame') || [];
let elem = elems[0];
this.pickerRoot.style.pointerEvents = '';
return elem;
},
highlightElementAtPoint: function (mx, my) {
const elem = this.elementFromPoint(mx, my);
this.highlightElements(elem ? [elem] : []);
},
filterElementAtPoint: function (mx, my) {
if (this.filtersFrom(mx, my) === 0) { return; }
this.showDialog();
},
onKeyPressed: function (ev) {
// Esc
if (ev.key === 'Escape' || ev.which === 27) {
ev.stopPropagation();
ev.preventDefault();
this.quitPicker();
return;
}
},
onViewportChanged: function () {
this.highlightElements(this.targetElements, true);
},
startPicker: function () {
this.pickerRoot.focus();
this.pickerRoot.addEventListener('scroll', this.onViewportChanged, { passive: true });
this.pickerRoot.addEventListener('resize', this.onViewportChanged, { passive: true });
this.pickerRoot.addEventListener('keydown', this.onKeyPressed, true);
},
quitPicker: function () {
this.pickerRoot.removeEventListener('scroll', this.onViewportChanged, { passive: true });
this.pickerRoot.removeEventListener('resize', this.onViewportChanged, { passive: true });
this.pickerRoot.removeEventListener('keydown', this.onKeyPressed, true);
if (this.pickerRoot === null) { return; }
let parent = this.pickerRoot.parentElement;
this.pickerRoot.remove();
this.pickerRoot = null;
parent.focus();
},
onDialogMessage: function (msg) {
switch (msg.what) {
case 'start':
this.startPicker();
if (this.targetElements.length === 0) {
this.highlightElements([document.body], true);
}
break;
case 'quitPicker':
this.quitPicker();
break;
case 'highlightElementAtPoint':
this.highlightElementAtPoint(msg.mx, msg.my);
break;
case 'filterElementAtPoint':
this.filterElementAtPoint(msg.mx, msg.my);
break;
case 'togglePreview':
if (msg.state === false) {
this.highlightElements(this.targetElements, true);
}
break;
default:
break;
}
},
sendMessageToIframe: function (msg) {
this.pickerRoot.contentWindow.postMessage(msg, this.iframeHost);
},
showPicker: function () {
const self = this;
if (this.pickerRoot) {
return;
}
// loading
let loadingRoot = document.createElement('div');
loadingRoot.innerHTML = `
<div style='z-index:2147483647;background: #000; opacity: 0.3; position: fixed; top: 0px; left: 0px; width: 100%; height: 100%;'></div>
<div style="z-index:2147483647;border: 5px solid #f3f3f3; border-radius: 50%; border-top: 5px solid #3498db; width:4vw; height:4vw;min-width:30px;min-height:30px;max-width:50px;max-height:50px;animation: db_search_turn${randomCode} 2s linear infinite; margin: 20px; margin-left: 48%; top: 45%; position: fixed"></div>`;
document.documentElement.append(loadingRoot);
// iframe
const pickerRoot = document.createElement('iframe');
pickerRoot.setAttribute('name', 'myFrame');
pickerRoot.setAttribute('src', this.iframeHost + '/picker.html');
pickerRoot.style = `color-scheme:initial;box-shadow:none !important;display:block !important;height:100vh !important;left:0px !important;max-height:none !important;max-width:none !important;min-height:unset !important;min-width:unset !important;opacity:1 !important;pointer-events:auto !important;position:fixed !important;top: 0px !important;visibility:visible !important;width:100% !important;z-index:2147483647 !important;background:transparent !important;border-width:0px !important;border-style:initial !important;border-color:initial !important;border-image:initial !important;border-radius:0px !important;margin:0px !important;outline:0px !important;padding: 0px !important`;
pickerRoot.onload = function () {
setTimeout(() => {
loadingRoot.remove();
self.sendMessageToIframe({ what: 'connectionAccepted' })
}, 500);
};
this.pickerRoot = pickerRoot;
document.documentElement.append(pickerRoot);
},
}
//设置面板
const SettingPanel = {
config: [{ title: "", name: "", type: "", attrName: "", item: [{ code: "", text: "" }] }],
Create: function (popBoxEl) {
let self = this;
let settingHtml = [];
this.InitConfig();
settingHtml.push(Utils.StringFormat('<div class="setting{0}">', randomCode));
for (let index = 0; index < this.config.length; index++) {
let configItem = this.config[index];
settingHtml.push(Utils.StringFormat(`<div class="configItem{0}"><div class="title{0}">{1}</div><div class="right{0}">`, randomCode, configItem.title));
for (let itemIndex = 0; itemIndex < configItem.item.length; itemIndex++) {
let itemObj = configItem.item[itemIndex];
settingHtml.push(Utils.StringFormat('<label><input type="radio" name="search{3}{0}" value="{1}">{2}</label>', randomCode, itemObj.code, itemObj.text, configItem.name));
}
settingHtml.push('</div></div>');
}
settingHtml.push(Utils.StringFormat(`<div class="bottom{0}"><button id="saveBtn{0}">保存</button><span id="saveStatus{0}" class="msg{0}">设置已保存。</span></div></div>`, randomCode));
let settingHtmlStr = settingHtml.join("");
Panel.popBoxEl = popBoxEl;
Panel.Create("设置", "auto bottom", false, settingHtmlStr, function ($panel) {
$panel.css({
position: "fixed",
top: "120px"
});
self.Update();
//保存设置
$panel.find(Utils.StringFormat("#panelBody{0} #saveBtn{0}", randomCode)).click(function (e) {
self.config.forEach((item) => {
let selecter = `#panelBody{0} input[name='search${item.name}{0}']:checked`;
let value = $panel.find(Utils.StringFormat(selecter, randomCode)).val();
SettingOptions[item.attrName] = value;
});
Utils.SetSettingOptions();
$panel.find(Utils.StringFormat("#panelBody{0} #saveStatus{0}", randomCode)).fadeIn(function () {
setTimeout(function () {
$panel.find(Utils.StringFormat("#panelBody{0} #saveStatus{0}", randomCode)).fadeOut();
}, 1500);
});
});
});
},
Update: function () {
let self = this;
Utils.GetSettingOptions();
Panel.Update(function ($panel) {
self.config.forEach((item) => {
let selecter = `#panelBody{0} input[name='search${item.name}{0}'][value='{1}']`;
$panel.find(Utils.StringFormat(selecter, randomCode, SettingOptions[item.attrName])).prop("checked", true);
});
});
},
InitConfig: function () {
this.config = [];
let engineConfigObj = { title: "默认搜索引擎", name: "Engine", attrName: "defaultsearchengine", item: [] };
/*for (let k in Search.searchEngineList) {
if (Search.searchEngineList.hasOwnProperty(k)) {
let v = Search.searchEngineList[k].codeText;
engineConfigObj.item.push({ code: k, text: v });
}
}*/
this.config.push(engineConfigObj);
let patternConfigObj = { title: "搜索模式", name: "Pattern", attrName: "searchPattern", item: [{ code: "automatic", text: "自动" }, { code: "manual", text: "手动" }] };
this.config.push(patternConfigObj);
let selectConfigObj = { title: "划词模式", name: "Select", attrName: "selectPattern", item: [{ code: "select", text: "划词" }, { code: "hold", text: "划词键 + 划词" }] };
this.config.push(selectConfigObj);
let keyConfigObj = { title: "划词键", name: "Key", attrName: "selectKey", item: [{ code: "Ctrl", text: "Ctrl" }, { code: "Alt", text: "Alt" }] };
this.config.push(keyConfigObj);
let positionConfigObj = { title: "图标位置", name: "Position", attrName: "selectIconPosition", item: [{ code: "right", text: "右" }, { code: "left", text: "左" }, { code: "top", text: "上" }] };
this.config.push(positionConfigObj);
},
CreateStyle: function () {
let s = "";
s += Utils.StringFormat("#panelBody{0} .setting{0} .configItem{0}{display:flex;padding:5px}#panelBody{0} .configItem{0} .title{0}{width:90px;font-size: 14px}#panelBody{0} .configItem{0} .right{0}{margin-left:10px}#panelBody{0} .configItem{0} .right{0} label{cursor:pointer;display:inline-block;min-width:60px}#panelBody{0} .configItem{0} .right{0} input{cursor:pointer;vertical-align:middle;margin-top:-2px;margin-bottom:1px}", randomCode);
s += Utils.StringFormat("#panelBody{0} .setting{0} button{border:0.5px solid black;margin:5px;padding:1px 5px;border-radius:revert;font:revert}#panelBody{0} .setting{0} .bottom{0} .msg{0}{display: none; margin-left:5px;background-color:#fff1a8;padding:3px}", randomCode);
return s;
}
};
//主程序
const WebSearchlate = function () {
const $doc = $(document);
const $body = $("html body");
const createHtml = function () {
const wordSearchIconHtml = Utils.StringFormat('<div id="wordSearch{0}" class="wordSearch{0}"><div class="wordSearchIcon{0}"></div></div>', randomCode);
$body.append(Utils.StringFormat('<div id="webSearch{0}">', randomCode) + wordSearchIconHtml + '</div>');
};
const createStyle = function () {
//尽可能避开csp认证
GM_xmlhttpRequest({
method: "get",
url: "https://cdn.jsdelivr.net/gh/zyufstudio/jQuery@master/jPopBox/dist/jPopBox.min.css",
onload: function (r) {
GM_addStyle(r.responseText + ".JPopBox-tip-white{width: 482px;max-width: 550px;min-width: 450px}");
}
});
let s = Utils.StringFormat("@keyframes db_search_turn{0}{0%{transform:rotate(0deg)}25%{transform:rotate(90deg)}50%{transform:rotate(180deg)}75%{transform:rotate(270deg)}100%{transform:rotate(360deg)}}", randomCode);
s += Utils.StringFormat(".wordSearch{0}{background-color: rgb(245, 245, 245);box-sizing: content-box;cursor: pointer;z-index: 2147483647;border-width: 1px;border-style: solid;border-color: rgb(220, 220, 220);border-image: initial;border-radius: 5px;padding: 0.5px;position: absolute;display: none} .wordSearch{0}.animate{animation: db_search_turn{0} 5s linear infinite}", randomCode);
s += Utils.StringFormat(".wordSearchIcon{0}{background-image: url({1});background-size: 25px;height: 25px;width: 25px}", randomCode, Images.IconBase64);
s += Panel.CreateStyle();
s += SettingPanel.CreateStyle();
GM_addStyle(s);
};
const RegMenu = function () {
GM_registerMenuCommand("设置", function () {
if (DoubanPickerTool.pickerRoot) {
DoubanPickerTool.quitPicker();
}
$("div#wordSearch" + randomCode).hide();
SearchMovie.Clear();
SearchBook.Clear();
Panel.Destroy();
SettingPanel.Create($body);
});
GM_registerMenuCommand("进入取词模式", function () {
if (DoubanPickerTool.pickerRoot) {
return;
}
$("div#wordSearch" + randomCode).hide();
SearchMovie.Clear();
SearchBook.Clear();
Panel.Destroy();
DoubanPickerTool.showPicker();
});
};
this.init = function () {
SearchMovie.RegisterEngine();
SearchBook.RegisterEngine();
createStyle();
createHtml();
RegMenu();
Utils.GetSettingOptions();
DoubanPickerTool.initDoubanPicker(Urls.IframePageHost)
};
};