// ==UserScript==
// @name MWI Watch Market - 奶牛的市场关注监视
// @namespace http://tampermonkey.net/
// @version test0.0.11
// @description 监视下心怡物品的当前价格,还有1day和3day的数据,数据采集于MWIAPI,1day,3day数据为自己生成,没找到获取强化装备市场数据的地方,所以无法监控强化装备市场,如果有误或者有问题可以在MWIItemWatchData的仓库下给我留言
// @author lzy
// @license MIT
// @match https://www.milkywayidle.com/*
// @grant GM_addStyle
// ==/UserScript==
(function () {
"use strict";
let market; //当前的市场数据
let itemCNname; //物品的翻译数据
let db; //indexedDB用于保存一些用户的历史数据
const WatchStoreName = "watch";
const LogStoreName = "log";
const isOnline = true; //在线获取数据开关,频繁获取github容易被ban
const ShowButtonId = "mkWatchButton", //显示按钮
CleanButtonId = "mkWatchCleanButton", //清除按钮
RefreshButtonId = "mkWatchRefreshButton", //刷新按钮
HideButtonId = "mkWatchHideButton", //隐藏按钮
BoxClass = "mkWatchBox", //主体盒子
HeaderClass = "mkWatchBox_Header",
HeaderLabelClass = "mkWatchBox_Header_Label", //标题
HeaderActionClass = "mkWatchBox_Header_Action", //操作按钮
ActionClass = "mkWatchBox_Action", //操作按钮
BoxContainerClass = "mkWatchBox_ItemsWatchContainer", //主体容器
ItemsClass = "mkWatchBox_Items", //物品容器
ItemsAddInputId = "mkWatchBox_Items_Input_Add", //物品输入框
ItemsAddSelectId = "mkWatchBox_Items_Select_Add", //物品选择框
ItemsRemoveInputId = "mkWatchBox_Items_Input_Remove", //物品输入框
ItemsRemoveSelectId = "mkWatchBox_Items_Select_Remove", //物品选择框
ItemsAddClass = "mkWatchBox_Items_Add", //物品容器
ItemsRemoveClass = "mkWatchBox_Items_Remove", //物品容器
ItemNameClass = "mkWatchBox_Items_Name", //物品名称
ItemAskClass = "mkWatchBox_Items_Ask", //物品出售价格
ItemBidClass = "mkWatchBox_Items_Bid", //物品收购价格
ItemGroupClass = "mkWatchBox_Items_Group"; //物品收购价格
let saveedItems = []; //保存的物品列表
let data24h, data3day; //24小时和3天的历史价格数据
function init() {
const p1 = getMarkets();
const p2 = initIndexedDb();
const p3 = getItemsList();
const p4 = getItemLogMarkets();
Promise.all([p1, p2, p3, p4]).then((res) => {
console.info("数据获取完毕");
initHtml();
});
}
async function getMarkets() {
//获取当前数据
try {
let res;
if (isOnline) {
res = await fetch(
"https://raw.githubusercontent.com/holychikenz/MWIApi/main/milkyapi.json",
); //在线数据
} else {
res = await fetch("./milkyapi.json"); //本地测试数据
}
const data = await res.json();
market = data.market;
} catch (err) {
market = null;
console.error("获取市场数据失败");
}
return market;
}
async function getItemLogMarkets() {
//获取处理过后的一个历史价格数据
try {
if (isOnline) {
let res24h = await fetch(
"https://happyplum.github.io/MWIItemWatchData/1days.json",
);
data24h = await res24h.json();
let res3day = await fetch(
"https://happyplum.github.io/MWIItemWatchData/3days.json",
);
data3day = await res3day.json();
} else {
let res24h = await fetch("./node-getMWIData/dist/1days.json");
data24h = await res24h.json();
let res3day = await fetch("./node-getMWIData/dist/3days.json");
data3day = await res3day.json();
}
} catch (err) {}
}
function initIndexedDb() {
return new Promise((resolve, reject) => {
const req = indexedDB.open("milk", 1);
req.onerror = (err) => {
console.error("不支持indexedDB?", err);
reject(err);
};
req.onsuccess = (event) => {
db = event.target.result;
db.setData = setData;
db.getData = getData;
db.getAllData = getAllData;
resolve(db);
};
req.onupgradeneeded = (event) => {
const db = event.target.result;
if (!db.objectStoreNames.contains(WatchStoreName)) {
db.createObjectStore(WatchStoreName, { autoIncrement: true });
}
if (!db.objectStoreNames.contains(LogStoreName)) {
db.createObjectStore(LogStoreName, { autoIncrement: true });
}
};
});
}
async function setData(key, value = {}, tableName = WatchStoreName) {
if (!db) await initIndexedDb();
return new Promise((resolve, reject) => {
try {
if (!db.objectStoreNames.contains(tableName)) {
reject(new Error(`Object store "${tableName}" not found`));
return;
}
const transaction = db.transaction(tableName, "readwrite");
const request = transaction
.objectStore(tableName)
.put({ key, ...value }, key);
request.onsuccess = () => {
resolve();
};
request.onerror = (error) => {
reject(error);
};
transaction.onerror = (error) => {
reject(error);
};
} catch (error) {
reject(error);
}
});
}
async function getData(key, tableName = WatchStoreName) {
if (!db) await initIndexedDb();
return new Promise((resolve, reject) => {
const getRequest = db
.transaction(tableName, "readonly")
.objectStore(tableName)
.get(key);
getRequest.onsuccess = (event) => {
resolve(event.target.result);
};
getRequest.onerror = (error) => {
reject(error);
};
});
}
async function delData(key, tableName = WatchStoreName) {
if (!db) await initIndexedDb();
return new Promise((resolve, reject) => {
const getRequest = db
.transaction(tableName, "readwrite")
.objectStore(tableName)
.delete(key);
getRequest.onsuccess = (event) => {
resolve(event.target.result);
};
getRequest.onerror = (error) => {
reject(error);
};
});
}
async function cleanData(tableName = WatchStoreName) {
if (!db) await initIndexedDb();
return new Promise((resolve, reject) => {
try {
if (!db.objectStoreNames.contains(tableName)) {
reject(new Error(`Object store "${tableName}" not found`));
return;
}
const transaction = db.transaction(tableName, "readwrite");
transaction.objectStore(tableName).clear();
transaction.oncomplete = () => {
resolve();
};
transaction.onerror = (error) => {
reject(error);
};
} catch (error) {
reject(error);
}
});
}
async function getAllData(tableName = WatchStoreName) {
if (!db) await initIndexedDb();
return new Promise((resolve, reject) => {
const getRequest = db
.transaction(tableName, "readonly")
.objectStore(tableName)
.getAll();
getRequest.onsuccess = (event) => {
resolve(event.target.result);
};
getRequest.onerror = (error) => {
reject(error);
};
});
}
async function getItemsList() {
let res;
if (isOnline) {
res = await fetch(
"https://happyplum.github.io/MWIItemWatchData/items.json",
);
} else {
res = await fetch("./node-getMWIData/dist/items.json");
}
const data = await res.json();
itemCNname = data;
}
function getCNName(key) {
const itemKey = key
.toLocaleLowerCase()
.replace(/'/g, "")
.replace(/ /g, "_");
return itemCNname[`/items/${itemKey}`];
}
function createHtml() {
const html = `
<div class="${BoxClass}">
<div class="${HeaderClass}">
<div class="${HeaderLabelClass}">
市场物品监测
</div>
<div class="${HeaderActionClass}">
<div id="${CleanButtonId}"><?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746635238249" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4288" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M874.666667 241.066667h-202.666667V170.666667c0-40.533333-34.133333-74.666667-74.666667-74.666667h-170.666666c-40.533333 0-74.666667 34.133333-74.666667 74.666667v70.4H149.333333c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h53.333334V853.333333c0 40.533333 34.133333 74.666667 74.666666 74.666667h469.333334c40.533333 0 74.666667-34.133333 74.666666-74.666667V305.066667H874.666667c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32zM416 170.666667c0-6.4 4.266667-10.666667 10.666667-10.666667h170.666666c6.4 0 10.666667 4.266667 10.666667 10.666667v70.4h-192V170.666667z m341.333333 682.666666c0 6.4-4.266667 10.666667-10.666666 10.666667H277.333333c-6.4 0-10.666667-4.266667-10.666666-10.666667V309.333333h490.666666V853.333333z" p-id="4289"></path><path d="M426.666667 736c17.066667 0 32-14.933333 32-32V490.666667c0-17.066667-14.933333-32-32-32s-32 14.933333-32 32v213.333333c0 17.066667 14.933333 32 32 32zM597.333333 736c17.066667 0 32-14.933333 32-32V490.666667c0-17.066667-14.933333-32-32-32s-32 14.933333-32 32v213.333333c0 17.066667 14.933333 32 32 32z" p-id="4290"></path></svg></div>
<div id="${RefreshButtonId}"><?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746635228519" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4141" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M934.4 206.933333c-17.066667-4.266667-34.133333 6.4-38.4 23.466667l-23.466667 87.466667C797.866667 183.466667 654.933333 96 497.066667 96 264.533333 96 74.666667 281.6 74.666667 512s189.866667 416 422.4 416c179.2 0 339.2-110.933333 398.933333-275.2 6.4-17.066667-2.133333-34.133333-19.2-40.533333-17.066667-6.4-34.133333 2.133333-40.533333 19.2-51.2 138.666667-187.733333 232.533333-339.2 232.533333C298.666667 864 138.666667 706.133333 138.666667 512S300.8 160 497.066667 160c145.066667 0 277.333333 87.466667 330.666666 217.6l-128-36.266667c-17.066667-4.266667-34.133333 6.4-38.4 23.466667-4.266667 17.066667 6.4 34.133333 23.466667 38.4l185.6 49.066667c2.133333 0 6.4 2.133333 8.533333 2.133333 6.4 0 10.666667-2.133333 17.066667-4.266667 6.4-4.266667 12.8-10.666667 14.933333-19.2l49.066667-185.6c0-17.066667-8.533333-34.133333-25.6-38.4z" p-id="4142"></path></svg></div>
<div id="${HideButtonId}"><?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746635265487" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4440" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M955.733333 492.8c-6.4-12.8-162.133333-317.866667-443.733333-317.866667-23.466667 0-46.933333 2.133333-70.4 6.4-17.066667 4.266667-29.866667 19.2-25.6 36.266667 4.266667 17.066667 19.2 29.866667 36.266667 25.6 19.2-4.266667 38.4-4.266667 57.6-4.266667 209.066667 0 345.6 209.066667 379.733333 266.666667-10.666667 19.2-32 53.333333-64 91.733333-10.666667 12.8-8.533333 34.133333 4.266667 44.8 6.4 4.266667 12.8 6.4 21.333333 6.4s19.2-4.266667 25.6-10.666666c51.2-61.866667 78.933333-115.2 78.933333-117.333334 6.4-8.533333 6.4-19.2 0-27.733333zM215.466667 125.866667c-12.8-12.8-32-12.8-44.8 0-12.8 12.8-12.8 32 0 44.8l91.733333 91.733333C138.666667 354.133333 72.533333 484.266667 68.266667 490.666667c-4.266667 8.533333-4.266667 19.2 0 29.866666 6.4 12.8 162.133333 315.733333 443.733333 315.733334 83.2 0 164.266667-27.733333 241.066667-81.066667l96 96c6.4 6.4 14.933333 8.533333 23.466666 8.533333s17.066667-2.133333 23.466667-8.533333c12.8-12.8 12.8-32 0-44.8L215.466667 125.866667z m243.2 334.933333l104.533333 104.533333c-12.8 12.8-32 21.333333-51.2 21.333334-40.533333 0-74.666667-34.133333-74.666667-74.666667 0-19.2 8.533333-38.4 21.333334-51.2zM512 772.266667c-209.066667 0-345.6-209.066667-379.733333-266.666667 21.333333-36.266667 81.066667-130.133333 174.933333-196.266667l104.533333 104.533334c-25.6 25.6-38.4 59.733333-38.4 96 0 76.8 61.866667 138.666667 138.666667 138.666666 36.266667 0 70.4-14.933333 96-38.4l98.133333 98.133334c-61.866667 42.666667-128 64-194.133333 64z" p-id="4441"></path></svg></div>
</div>
</div>
<div class="${BoxContainerClass}">
</div>
<div class="${ActionClass}">
<input id="${ItemsAddInputId}" placeholder="物品名称筛选" autocomplete="off" /><select id="${ItemsAddSelectId}">
</select>
<div class="${ItemsAddClass}"><?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746635130485" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3390" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512 74.666667C270.933333 74.666667 74.666667 270.933333 74.666667 512S270.933333 949.333333 512 949.333333 949.333333 753.066667 949.333333 512 753.066667 74.666667 512 74.666667z m0 810.666666c-204.8 0-373.333333-168.533333-373.333333-373.333333S307.2 138.666667 512 138.666667 885.333333 307.2 885.333333 512 716.8 885.333333 512 885.333333z" p-id="3391"></path><path d="M682.666667 480h-138.666667V341.333333c0-17.066667-14.933333-32-32-32s-32 14.933333-32 32v138.666667H341.333333c-17.066667 0-32 14.933333-32 32s14.933333 32 32 32h138.666667V682.666667c0 17.066667 14.933333 32 32 32s32-14.933333 32-32v-138.666667H682.666667c17.066667 0 32-14.933333 32-32s-14.933333-32-32-32z" p-id="3392"></path></svg></div>
</div>
<div class="${ActionClass}">
<input id="${ItemsRemoveInputId}" placeholder="物品名称筛选" autocomplete="off" /><select id="${ItemsRemoveSelectId}">
</select>
<div class="${ItemsRemoveClass}"><?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746635197834" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3987" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M512 949.333333C270.933333 949.333333 74.666667 753.066667 74.666667 512S270.933333 74.666667 512 74.666667 949.333333 270.933333 949.333333 512 753.066667 949.333333 512 949.333333z m0-810.666666C307.2 138.666667 138.666667 307.2 138.666667 512S307.2 885.333333 512 885.333333 885.333333 716.8 885.333333 512 716.8 138.666667 512 138.666667z" p-id="3988"></path><path d="M682.666667 544H341.333333c-17.066667 0-32-14.933333-32-32s14.933333-32 32-32h341.333334c17.066667 0 32 14.933333 32 32s-14.933333 32-32 32z" p-id="3989"></path></svg></div>
</div>
</div>`;
return html;
}
async function initHtml() {
if (!document.body) {
//如果body不存在,可能html还没绘制完毕,延迟1秒再执行
return setTimeout(initHtml, 1000);
}
//插入主体
const abody = createHtml();
document.body.insertAdjacentHTML("beforeend", abody);
//插入占位按钮,还没想好用什么图标,先放个按钮,用于显示框架
const aicon = `<div id="${ShowButtonId}"><?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1746635280605" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4593" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M789.333333 74.666667H234.666667C194.133333 74.666667 160 108.8 160 149.333333v725.333334c0 40.533333 34.133333 74.666667 74.666667 74.666666h554.666666c40.533333 0 74.666667-34.133333 74.666667-74.666666V149.333333c0-40.533333-34.133333-74.666667-74.666667-74.666666z m-138.666666 64v296.533333L576 364.8c-6.4-6.4-14.933333-8.533333-21.333333-8.533333-8.533333 0-17.066667 2.133333-21.333334 8.533333l-74.666666 72.533333v-298.666666h192z m149.333333 736c0 6.4-4.266667 10.666667-10.666667 10.666666H234.666667c-6.4 0-10.666667-4.266667-10.666667-10.666666V149.333333c0-6.4 4.266667-10.666667 10.666667-10.666666h160v322.133333c0 14.933333 6.4 27.733333 14.933333 36.266667 21.333333 21.333333 53.333333 21.333333 74.666667 0l70.4-68.266667 70.4 68.266667c10.666667 10.666667 23.466667 14.933333 36.266666 14.933333 29.866667 0 53.333333-23.466667 53.333334-53.333333v-320H789.333333c6.4 0 10.666667 4.266667 10.666667 10.666666v725.333334z" p-id="4594"></path></svg></div>`;
document.body.insertAdjacentHTML("beforeend", aicon);
//添加下拉选框
refreshItems();
//绑定框体事件
bindButtonListener();
}
function bindButtonListener() {
//外框体事件
const showbutton = document.getElementById(ShowButtonId);
showbutton.addEventListener("click", showOrHideBox);
const hidebutton = document.getElementById(HideButtonId);
hidebutton.addEventListener("click", HideBox);
const refreshbutton = document.getElementById(RefreshButtonId);
refreshbutton.addEventListener("click", refresh);
const cleanbutton = document.getElementById(CleanButtonId);
cleanbutton.addEventListener("click", clean);
const headerLabel = document.querySelector(`.${HeaderLabelClass}`);
headerLabel.addEventListener("mousedown", moveBox);
//添加删除事件
const addSearch = document.querySelector(`#${ItemsAddInputId}`);
addSearch.addEventListener("input", searchAddItem);
const addbutton = document.querySelector(`.${ItemsAddClass}`);
addbutton.addEventListener("click", addWatchItem);
const removeSearch = document.querySelector(`#${ItemsRemoveInputId}`);
removeSearch.addEventListener("input", searchRemoveItem);
const removebutton = document.querySelector(`.${ItemsRemoveClass}`);
removebutton.addEventListener("click", removeWatchItem);
}
function moveBox(e) {
//拖动逻辑
const box = document.querySelector(`.${BoxClass}`);
let x = e.clientX;
let y = e.clientY;
document.onmousemove = function (e) {
let nowX = e.clientX;
let nowY = e.clientY;
let disX = nowX - x;
let disY = nowY - y;
box.style.left = `${box.offsetLeft + disX}px`;
box.style.top = `${box.offsetTop + disY}px`;
x = nowX;
y = nowY;
};
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup = null;
};
}
function showOrHideBox() {
const box = document.querySelector(`.${BoxClass}`);
if (box.style.display === "none") {
ShowBox();
} else {
HideBox();
}
}
function ShowBox() {
const box = document.querySelector(`.${BoxClass}`);
box.style.display = "block";
}
function HideBox() {
const box = document.querySelector(`.${BoxClass}`);
box.style.display = "none";
}
let reing = false;
async function refresh() {
if (reing) {
//给RefreshButtonId增加reloading的class
alert("最近刷新过了,10秒后可再刷新");
return;
}
reing = true;
const refreshbutton = document.getElementById(RefreshButtonId);
refreshbutton.classList.add("reloading");
//清空容器,来增加个过度的感觉,不然感觉反馈不太明显
const container = document.querySelector(`.${BoxContainerClass}`);
container.innerHTML = "";
//刷新逻辑,需要重新获取价格数据,然后重新绘制items
const p1 = getMarkets();
const p2 = getItemLogMarkets();
Promise.all([p1, p2]).then((res) => {
refreshItems();
console.info("刷新完毕");
setTimeout(() => {
reing = false;
refreshbutton.classList.remove("reloading");
}, 10 * 1000);
});
}
function clean() {
cleanData(WatchStoreName);
cleanData(LogStoreName);
refreshItems();
}
let addList = []; //添加的下拉列表
let removeList = []; //删除的下拉列表
async function genSelectOptions() {
//根据market生成select选项,显示需要转换成中文,value为key
//分为3类,添加,删除,未知3类分批,未知类型不需要添加到select中,但是需要打印用来标注
if (!market) return;
saveedItems = await getAllData();
addList = [];
removeList = [];
Object.keys(market).forEach((key) => {
let value = getCNName(key);
if (!value) {
console.log(`没有找到${key}的翻译`);
return;
}
const option = { value: key, text: value };
if (saveedItems.find((item) => item.key === key)) {
removeList.push(option);
} else {
addList.push(option);
}
});
}
let filterAddList = [];
function searchAddItem(e) {
const str = e.target.value;
filterAddList = addList.filter((item) => {
return item.text.includes(str);
});
renderAddSelectOption();
}
let filterRemoveList = [];
function searchRemoveItem(e) {
const str = e.target.value;
filterRemoveList = removeList.filter((item) => {
return item.text.includes(str);
});
renderRemoveSelectOption();
}
function renderAddSelectOption() {
//添加下拉相关
const addSelect = document.querySelector(`#${ItemsAddSelectId}`);
addSelect.innerHTML = "";
const list = filterAddList.length > 0 ? filterAddList : addList;
list.forEach((item) => {
const option = document.createElement("option");
option.value = item.value;
option.text = item.text;
addSelect.add(option);
});
}
function renderRemoveSelectOption() {
//删除下拉相关
const removeSelect = document.querySelector(`#${ItemsRemoveSelectId}`);
removeSelect.innerHTML = "";
const list = filterRemoveList.length > 0 ? filterRemoveList : removeList;
list.forEach((item) => {
const option = document.createElement("option");
option.value = item.value;
option.text = item.text;
removeSelect.add(option);
});
}
async function addWatchItem() {
//获取当前select的值
const select = document.querySelector(`#${ItemsAddSelectId}`);
const key = select.value;
if (!key) return;
await setData(key, { index: 0, ae: -1 });
refreshItems(); //添加完毕后要刷新下
}
async function removeWatchItem() {
const select = document.querySelector(`#${ItemsRemoveSelectId}`);
const key = select.value;
if (!key) return;
await delData(key);
refreshItems(); //添加完毕后要刷新下
}
async function refreshItems() {
await genSelectOptions();
renderAddSelectOption();
renderRemoveSelectOption();
renderItems();
}
async function renderItems() {
//清空容器,可能和refresh阶段有点重复,放着反正也没事
const container = document.querySelector(`.${BoxContainerClass}`);
container.innerHTML = "";
if (!saveedItems) saveedItems = await getAllData();
if (saveedItems.length === 0) return;
//首先获取监听物品
const watchItems = saveedItems
.filter((item) => item.index !== -1)
.sort((a, b) => b.index - a.index);
watchItems.forEach((item) => {
const html = getItemHtml(item);
container.insertAdjacentHTML("beforeend", html);
});
}
function formatNum(num) {
const number = Number(num);
if (number > 1000000) {
return (number / 1000000).toFixed(1) + "M";
}
if (number > 1000) {
return (number / 1000).toFixed(1) + "K";
}
return number.toFixed(0) + "";
}
function getItemHtml(item) {
const key = item.key;
const name = getCNName(key);
return createItem(key, name);
}
function getslope(slope) {
if (slope > 0) {
return `↑`;
} else if (slope < 0) {
return `↓`;
}
return `→`;
}
function createItem(key, name) {
const m = market[key];
const oneDay = data24h[key];
const threeDay = data3day[key];
const html = `
<div class="${ItemsClass}">
<div class="${ItemNameClass}">${name}</div>
<div class="${ItemGroupClass}">
<div class="${ItemAskClass}">ask:${formatNum(m.ask)}</div>
<div class="${ItemBidClass}">bid:${formatNum(m.bid)}</div>
</div>
<div class="${ItemBidClass}">1day ${getslope(oneDay.slope)}</div>
<div class="${ItemBidClass}">avgCom:${formatNum(
oneDay.avgCombined,
)}</div>
<div class="${ItemGroupClass}">
<div class="${ItemBidClass}">maxAsk:${formatNum(
oneDay.maxAsk,
)}</div>
<div class="${ItemBidClass}">avgAsk:${formatNum(
oneDay.avgAsk,
)}</div>
<div class="${ItemBidClass}">minAsk:${formatNum(
oneDay.minAsk,
)}</div>
</div>
<div class="${ItemGroupClass}">
<div class="${ItemBidClass}">maxBid:${formatNum(
oneDay.maxBid,
)}</div>
<div class="${ItemBidClass}">avgBid:${formatNum(
oneDay.avgBid,
)}</div>
<div class="${ItemBidClass}">minBid:${formatNum(
oneDay.minBid,
)}</div>
</div>
<div class="${ItemBidClass}">3day ${getslope(threeDay.slope)}</div>
<div class="${ItemBidClass}">avgCom:${formatNum(
threeDay.avgCombined,
)}</div>
<div class="${ItemGroupClass}">
<div class="${ItemBidClass}">maxAsk:${formatNum(
threeDay.maxAsk,
)}</div>
<div class="${ItemBidClass}">avgAsk:${formatNum(threeDay.avgAsk)}</div>
<div class="${ItemBidClass}">minAsk:${formatNum(
threeDay.minAsk,
)}</div>
</div>
<div class="${ItemGroupClass}">
<div class="${ItemBidClass}">maxBid:${formatNum(
threeDay.maxBid,
)}</div>
<div class="${ItemBidClass}">avgBid:${formatNum(threeDay.avgBid)}</div>
<div class="${ItemBidClass}">minBid:${formatNum(
threeDay.minBid,
)}</div>
</div>
</div>`;
return html;
}
function addClass() {
let modelStyle = `
#mkWatchButton {
position: absolute;
right: 300px;
top: 40px;
width: 20px;
height: 20px;
cursor: pointer;
}
#mkWatchButton svg{
fill: #faa21e;
width: 20px;
height: 20px;
}
.mkWatchBox {
position: absolute;
z-index:1;
right: 240px;
top: 100px;
width: 380px;
min-height: 200px;
padding: 10px;
background: #033963;
border: #74b9ff solid 1px;
border-radius: 8px;
color: #fff;
}
.mkWatchBox .mkWatchBox_Header {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
display: flex;
justify-content: flex-end;
}
.mkWatchBox .mkWatchBox_Header .mkWatchBox_Header_Label {
flex: 1;
user-select: none;
cursor: move;
}
.mkWatchBox .mkWatchBox_Header .mkWatchBox_Header_Action {
display: flex;
}
.mkWatchBox_ItemsWatchContainer {
display: flex;
min-height: 88px;
flex-wrap: wrap;
overflow: auto;
max-height: 440px;
}
.mkWatchBox_ItemsWatchContainer .mkWatchBox_Items {
height: 430px;
width: 100px;
border: #fff solid 1px;
border-radius: 3px;
padding: 4px;
margin: 4px;
font-size: 12px;
}
#mkWatchBox_Items_Input_Add,
#mkWatchBox_Items_Input_Remove {
width: 100px;
}
#mkWatchBox_Items_Select_Add,
#mkWatchBox_Items_Select_Remove {
width: 200px;
margin-left: 4px;
}
.mkWatchBox_Items {
text-align: center;
}
.mkWatchBox_Items_Group {
border: 1px solid #74b9ff;
padding: 4px;
margin: 4px 0px;
}
#mkWatchCleanButton,
#mkWatchRefreshButton,
#mkWatchHideButton {
cursor: pointer;
margin: 0px 4px;
}
#mkWatchCleanButton svg,
#mkWatchRefreshButton svg,
#mkWatchHideButton svg {
fill: #fff;
width: 20px;
height: 20px;
}
.mkWatchBox_Items_Add,
.mkWatchBox_Items_Remove {
cursor: pointer;
}
.mkWatchBox_Items_Add svg,
.mkWatchBox_Items_Remove svg {
width: 20px;
height: 20px;
fill: #fff;
margin: 0px 4px;
}
.mkWatchBox_Action {
display: flex;
}
.reloading#mkWatchRefreshButton svg {
fill: #aaa;
cursor: not-allowed;
}`;
try {
GM_addStyle(modelStyle);
} catch (err) {}
}
addClass();
init();
})();