// ==UserScript==
// @name hwmFriendsTabs
// @author Tamozhnya1
// @namespace Tamozhnya1
// @description Сортировка друзей по группам, заметки на pl_info
// @version 0.98
// @include https://www.heroeswm.ru/home.php
// @include https://www.heroeswm.ru/friends.php
// @include https://www.lordswm.com/home.php
// @include https://www.lordswm.com/friends.php
// @include https://my.lordswm.com/home.php
// @include https://my.lordswm.com/friends.php
// @include *heroeswm.ru/pl_info.php*
// @include *lordswm.com/pl_info.php*
// @license MIT
// ==/UserScript==
const playerIdMatch = document.cookie.match(/pl_id=(\d+)/);
if(!playerIdMatch) {
return;
}
const PlayerId = playerIdMatch[1];
addStyle(`
.tablinks {
display: flex;
flex-wrap: wrap;
flex-direction: row;
}
.tablink {
background-color: #555;
color: white;
border: none;
outline: none;
cursor: pointer;
padding: 7px 8px;
font-size: 10pt;
width: auto;
}
.tablink:hover {
background-color: #777;
}
.tabcontent {
padding: 20px 20px;
height: 100%;
}
`);
const isEn = document.documentElement.lang == "en";
const isNewPersonPage = document.querySelector("div#hwm_no_zoom") ? true : false;
main();
function main() {
if(location.pathname == "/pl_info.php") {
const viewingPlayerId = getUrlParamValue(location.href, "id");
if(viewingPlayerId != PlayerId) {
const container = document.querySelector("table.wblight > tbody > tr > td:nth-child(2)");
container.align = "left";
const playerInfoInput = createElement("input", { type: "text", style: "width: 150px;", value: getValue(`PlayerInfo${viewingPlayerId}`, ""), title: isEn ? "Notes" : "Заметки" });
playerInfoInput.addEventListener("change", function() { setValue(`PlayerInfo${viewingPlayerId}`, this.value); })
container.insertAdjacentElement("afterbegin", playerInfoInput);
const resourcesTable = container.querySelector("table");
resourcesTable.style.display = "inline-table";
resourcesTable.style.verticalAlign = "bottom";
}
return;
}
//deletePlayerValue("FriendsGroups");
if(!getPlayerValue("FriendsGroups")) {
setPlayerValue("FriendsGroups", JSON.stringify([isEn ? "Friends" : "Друзья", isEn ? "Familiar" : "Знакомые", isEn ? "Teachers" : "Учителя", isEn ? "Smiths" : "Кузнецы", isEn ? "Crafters" : "Крафтеры", isEn ? "Celebrities" : "Знаменитости", isEn ? "Clan" : "Клан", isEn ? "Enemies" : "Враги"]))
}
drawFriendsTabs();
}
function drawFriendsTabs() {
let friendsContainer;
let friendsRefs;
if(location.pathname == "/home.php") {
const friendsCaption = Array.from(document.querySelectorAll("a[href='friends.php']")).find(x => x.innerHTML.includes(isEn ? "Friends online" : "Друзья в игре"));
if(isNewPersonPage) {
friendsContainer = getParent(friendsCaption, "div", 2);
} else {
const friendsCaptionTr = friendsCaption.closest("tr");
const friendsTr = friendsCaptionTr.nextElementSibling;
friendsContainer = friendsTr.firstChild;
}
friendsRefs = Array.from(friendsContainer.querySelectorAll("a[href^='pl_info.php']"));
}
if(location.pathname == "/friends.php") {
const mainFriendsTable = document.querySelector("form[name=f] table");
mainFriendsTable.width = "";
mainFriendsTable.style.width = "auto;"
friendsRefs = Array.from(mainFriendsTable.querySelectorAll("a[href^='pl_info.php']"));
const mainFriendsRow = document.querySelector("form[name=f]").closest("table").rows[0];
mainFriendsRow.cells[0].style = "width: 30%;";
friendsContainer = addElement("td", mainFriendsRow, { style: `height: 100%;` });
}
friendsRefs.forEach(x => x.addEventListener("dragstart", function(e) { e.dataTransfer.setData("friendId", getUrlParamValue(e.target.href, "id")); }));
let friendsGroupsContainer = document.querySelector("div#friendsGroupsContainer");
if(!friendsGroupsContainer) {
friendsGroupsContainer = addElement("div", friendsContainer, { id: "friendsGroupsContainer", style: `position: relative; width: 100%; height: 100%; vertical-align: top;` });
} else {
friendsGroupsContainer.innerHTML = "";
}
const tabNames = JSON.parse(getPlayerValue("FriendsGroups"));
if(parseInt(getPlayerValue("CurrentFriendsTab", 0)) > tabNames.length - 1) {
setPlayerValue("CurrentFriendsTab", 0);
}
//console.log(tabNames)
const buttonsContainer = addElement("div", friendsGroupsContainer, { class: "tablinks" });
tabNames.forEach((tabName, tabIndex) => {
const button = addElement("button", buttonsContainer, { id: `showFriendsTabButton${tabIndex}`, class: "tablink", draggable: true, innerHTML: tabName });
button.addEventListener("click", function() { showTab(tabIndex); });
button.addEventListener("dragover", function(e) { e.preventDefault(); });
button.addEventListener("drop", function(e) {
e.preventDefault();
if(e.dataTransfer.getData("friendId")) {
addFiendToGroup(tabIndex, e.dataTransfer.getData("friendId")); // Принесли сюда друга
}
if(e.dataTransfer.getData("tabIndex")) {
swapGroups(tabIndex, parseInt(e.dataTransfer.getData("tabIndex"))); // Принесли сюда другую закладку
}
});
button.addEventListener("dragstart", function(e) { e.dataTransfer.setData("tabIndex", tabIndex); });
});
const button = addElement("button", buttonsContainer, { class: "tablink", innerHTML: "+", title: isEn ? "Add group" : "Добавить группу" });
button.addEventListener("click", function() {
const newTabNameInput = document.getElementById("newTabNameInput");
newTabNameInput.style.display = (newTabNameInput.style.display == "" ? "none" : "");
newTabNameInput.focus();
});
const newTabNameInput = addElement("input", button, { id: "newTabNameInput", type: "text", style: "display: none;" });
newTabNameInput.addEventListener("change", function() { addFriendsGroup(this.value); });
newTabNameInput.addEventListener("click", function(e) { e.stopPropagation(); });
const friendsGroupContainer = addElement("div", friendsGroupsContainer, { id: `friendsGroupContainer`, class: "tabcontent" });
friendsGroupContainer.addEventListener("dragover", function(e) { e.preventDefault(); });
friendsGroupContainer.addEventListener("drop", function(e) { e.preventDefault(); addFiendToGroup(undefined, e.dataTransfer.getData("friendId")); });
const basketDiv = addElement("div", friendsGroupsContainer, { style: "position: absolute; right: 0; bottom: 0;" });
const basket = addElement("img", basketDiv, { src: "https://dcdn.heroeswm.ru/i/artifacts/other/treasure.png", title: "Корзина", style: "width: 50px; height: 50px;" });
basket.addEventListener("dragover", function(e) { e.preventDefault(); });
basket.addEventListener("drop", function(e) { e.preventDefault(); e.stopPropagation(); deleteFriendsGroup(e.dataTransfer.getData("tabIndex"), e.dataTransfer.getData("friendId")); });
showTab();
}
function swapGroups(tabIndex, newTabIndex) {
const tabNames = JSON.parse(getPlayerValue("FriendsGroups"));
[tabNames[tabIndex], tabNames[newTabIndex]] = [tabNames[newTabIndex], tabNames[tabIndex]];
setPlayerValue("FriendsGroups", JSON.stringify(tabNames));
const group1 = getPlayerValue(`FriendsGroup${tabIndex}`, "[]");
const group2 = getPlayerValue(`FriendsGroup${newTabIndex}`, "[]");
setPlayerValue(`FriendsGroup${tabIndex}`, group2);
setPlayerValue(`FriendsGroup${newTabIndex}`, group1);
setPlayerValue("CurrentFriendsTab", tabIndex);
drawFriendsTabs();
}
function showTab(tabIndex = parseInt(getPlayerValue("CurrentFriendsTab", 0))) {
setPlayerValue("CurrentFriendsTab", tabIndex);
const friendsGroupContainer = document.getElementById("friendsGroupContainer");
Array.from(friendsGroupContainer.querySelectorAll("div[name=friendRefContainer]")).forEach(x => x.remove());
Array.from(document.getElementsByClassName("tablink")).forEach(x => x.style.backgroundColor = "");
const color = `hsl(${Math.random() * 360}, 100%, 75%)`;
document.querySelector("div#friendsGroupsContainer").style.backgroundColor = color;
document.querySelector(`#showFriendsTabButton${tabIndex}`).style.backgroundColor = color;
const group = JSON.parse(getPlayerValue(`FriendsGroup${tabIndex}`, "[]"));
removeArrayEmptyEntries(group);
//console.log(group);
setPlayerValue(`FriendsGroup${tabIndex}`, JSON.stringify(group));
const friendNotes = JSON.parse(getPlayerValue("friendNotes", "{}"));
for(const groupItem of group) {
const mainRef = document.querySelector(`a[href='pl_info.php?id=${groupItem}']`);
if(mainRef) {
//console.log((mainRef.querySelector("b") || mainRef).innerText);
const refDiv = addElement("div", friendsGroupContainer, { name: "friendRefContainer" });
const a = addElement("a", refDiv, { href: `pl_info.php?id=${groupItem}` });
addElement("b", a, {innerHTML: (mainRef.querySelector("b") || mainRef).innerText});
a.addEventListener("dragstart", function(e) { e.dataTransfer.setData("tabIndex", tabIndex); e.dataTransfer.setData("friendId", groupItem); });
const notesInput = addElement("input", refDiv, { type: "text", value: friendNotes[groupItem] || "", title: isEn ? "Notes" : "Заметки", style: `display: inline-block; width: ${isNewPersonPage ? 200 : 400}px;` });
notesInput.addEventListener("change", function() { savePlayerNote(groupItem, this.value); });
}
}
}
function savePlayerNote(playerId, note) {
const friendNotes = JSON.parse(getPlayerValue("friendNotes", "{}"));
friendNotes[playerId] = note;
setPlayerValue("friendNotes", JSON.stringify(friendNotes));
}
function addFiendToGroup(tabIndex, friendId) {
tabIndex = tabIndex || parseInt(getPlayerValue("CurrentFriendsTab", 0));
friendId = parseInt(friendId);
const group = JSON.parse(getPlayerValue(`FriendsGroup${tabIndex}`, "[]"));
if(!group.includes(friendId)) {
group.push(friendId);
setPlayerValue(`FriendsGroup${tabIndex}`, JSON.stringify(group));
drawFriendsTabs();
}
}
function addFriendsGroup(name) {
const tabNames = JSON.parse(getPlayerValue("FriendsGroups"));
if(name && !tabNames.includes(name)) {
tabNames.push(name);
setPlayerValue("FriendsGroups", JSON.stringify(tabNames));
drawFriendsTabs();
}
}
function deleteFriendsGroup(tabIndex, friendId) {
tabIndex = parseInt(tabIndex);
friendId = parseInt(friendId);
console.log(`tabIndex: ${tabIndex}, friendId: ${friendId}`);
if(friendId) {
const group = JSON.parse(getPlayerValue(`FriendsGroup${tabIndex}`, "[]"));
removeArrayValue(group, friendId);
console.log(group)
setPlayerValue(`FriendsGroup${tabIndex}`, JSON.stringify(group));
} else {
const tabNames = JSON.parse(getPlayerValue("FriendsGroups"));
for(let i = tabIndex; i < tabNames.length - 1; i++) {
setPlayerValue(`FriendsGroup${i}`, getPlayerValue(`FriendsGroup${i + 1}`, "[]"));
}
deletePlayerValue(`FriendsGroup${tabNames.length - 1}`);
tabNames.splice(tabIndex, 1);
setPlayerValue("FriendsGroups", JSON.stringify(tabNames));
setPlayerValue("CurrentFriendsTab", 0);
}
drawFriendsTabs();
}
// API
function getParent(element, parentType, number = 1) {
if(!element) {
return;
}
let result = element;
let foundNumber = 0;
while(result = result.parentNode) {
if(result.nodeName.toLowerCase() == parentType.toLowerCase()) {
foundNumber++;
if(foundNumber == number) {
return result;
}
}
}
}
function addElement(type, parent, data) {
let el = createElement(type, data);
if(parent) {
parent.appendChild(el);
}
return el;
}
function createElement(type, data) {
let el = document.createElement(type);
if(data) {
for(let key in data) {
if(key == "innerText" || key == "innerHTML") {
el[key] = data[key];
} else {
el.setAttribute(key, data[key]);
}
}
}
return el;
}
function addStyle(css) { addElement("style", document.head, { type: "text/css", innerHTML: css }); }
function getValue(key, defaultValue) { return localStorage[key] || defaultValue; };
function setValue(key, value) { localStorage[key] = value; };
function deleteValue(key) { return delete localStorage[key]; };
function listValues() { return Object.keys(localStorage); }
function getPlayerValue(key, defaultValue) { return localStorage[`${key}${PlayerId}`] || defaultValue; };
function setPlayerValue(key, value) { localStorage[`${key}${PlayerId}`] = value; };
function deletePlayerValue(key) { return delete localStorage[`${key}${PlayerId}`]; };
function getPlayerBool(valueName, defaultValue = false) { return getBool(valueName + PlayerId, defaultValue); }
function getBool(valueName, defaultValue = false) {
const value = getValue(valueName);
if(value != undefined) {
if(typeof(value) == "string") {
return value == "true";
}
if(typeof(value) == "boolean") {
return value;
}
}
return defaultValue;
}
function getRequest(url, overrideMimeType = "text/html; charset=windows-1251") {
return new Promise((resolve, reject) => {
GM.xmlHttpRequest({ method: "GET", url: url, overrideMimeType: overrideMimeType,
onload: function(response) { resolve((new DOMParser).parseFromString(response.responseText, "text/html")); },
onerror: function(error) { reject(error); }
});
});
}
function getUrlParamValue(url, paramName) { return (new URLSearchParams(url.split("?")[1])).get(paramName); }
function removeArrayValue(array, value) {
const index = array.indexOf(value);
if(index > -1) {
array.splice(index, 1);
}
}
function removeArrayEmptyEntries(array) {
let found = true;
while(found) {
const index = array.findIndex(x => !x);
if(index > -1) {
array.splice(index, 1);
} else {
found = false;
}
}
}