dailyhwm / SetsMaster

// ==UserScript==
// @name SetsMaster
// @author Tamozhnya1, Demin
// @namespace SetsMaster
// @description Меню наборов: армий, навыков, оружия. +Смена фракции.
// @homepage https://greasyfork.org/ru/scripts/446616-setsmaster
// @icon http://i.imgur.com/LZJFLgt.png
// @version 4.14.1
// @encoding utf-8

// @include *heroeswm.ru/*
// @include *lordswm.com/*

// @exclude /(clan_info|pl_info|forum_messages|frames|chat|rightcol|ch_box|ticker|brd)\.(html|php).*/
// @exclude */chat*
// @exclude */frames*

// @grant GM_deleteValue
// @grant GM_getValue
// @grant GM_listValues
// @grant GM_setValue
// @grant GM_addStyle
// @grant GM_log
// @grant GM_openInTab

// @license MIT
// ==/UserScript==

// 2012-2015 demin, 2012 Tamozhnya1
(function() {
// ==UserScript==
// @name           hwmSetsMaster
// @author         Tamozhnya1
// @namespace      Tamozhnya1
// @description    Меню наборов армии, навыков и оружия. Смена фракции.
// @version        4.14
// @encoding        utf-8
// @include        *heroeswm.ru/*
// @include        *lordswm.com/*
// @exclude        */rightcol.php*
// @exclude        */ch_box.php*
// @exclude        */chat*
// @exclude        */ticker.html*
// @exclude        */frames*
// @exclude        */brd.php*
// @grant          GM_deleteValue
// @grant          GM_getValue
// @grant          GM_listValues
// @grant          GM_setValue
// @grant          GM_addStyle
// @license        MIT
// ==/UserScript==

const windowObject = window.wrappedJSObject || unsafeWindow;
const elementType = { div: "div", a: "a", li: "li", table: "table", center: "center", input: "input", td: "td" };
const isPhotosPage = location.href.match('photo_pl_photos');
const Strings = {
        "ru": {
            Army: ustring("Армия"),
            Save: ustring("Сохранить"),
            Add: ustring("Добавить"),
            AddCurrent: ustring("Добавить текущий"),
            SetName: ustring("Наименование набора"),
            Delete: ustring("Удалить"),
            Talents: ustring("Навыки"),
            Weapon: ustring("Оружие"),
            RemoveAll: ustring("Снять все"),
            EnterJpg: "enter0.jpg",
            SignInTitle: "Войти",
            Castle: "Замок",
            Task: ustring("Задание")
        },
        "en": {
            Army: "Army",
            Save: "Save",
            Add: "Add",
            AddCurrent: "Add current",
            SetName: "Set name",
            Delete: "Delete",
            Talents: "Talents",
            Weapon: "Weapon",
            RemoveAll: "Un-equip all",
            EnterJpg: "enter0_eng.jpg",
            SignInTitle: "Sign in",
            Castle: "Castle",
            Task: "Task"
        }
    };
const LocalizedString = Strings[document.documentElement.lang];
var userName;
var currentFaction;

ensureGmMethods();
CalculateUserNameAndFaction();

/************************************************************************************************************/
const weaponSetsPreferences = {
    menuTitle: LocalizedString.Weapon,
    setReferencePage: "inventory.php",
    sets: new Array(),
    menuItems: {},
    currentMenuItem: undefined,
    refreshingPages: "home.php;inventory.php;pl_info.php",
    refreshingConditions: function() {
        if(/map.php/.test(location.href)) {
            let bolds = document.querySelectorAll("b");
            for(const bold of bolds) {
                if(bold.innerText.includes(LocalizedString.Task)) {
                    return true;
                }
            }
            let neut_right_block = document.querySelector("div[id='neut_right_block']");
            if(neut_right_block) {
                return true;
            }
        }
        return false;
    },
    getSets: function() {
        this.sets[0] = { number: 0, name: LocalizedString.RemoveAll, method: "GET", url: "inventory.php?all_off=100" };
        let lastSetNumber = GM_getValue(userName + "LastSetNumber", 0);
        for (let setNumber = 1; setNumber <= lastSetNumber; setNumber++) {
            let setName = GM_getValue(userName + "weaponSet" + setNumber);
            if (setName) {
                this.sets[setNumber] = { number: setNumber, name: setName, method: "GET", url: "inventory.php?all_on=" + setNumber, headers: null }
            }
        }
    },
    getCurrentSetName: function() { return userName + "currentWeaponSet"; },
    init: function() {
        if(/inventory.php/.test(location.href)) {
            let undressDiv = document.querySelector("div[id ='undress_all_div']");
            addSetChangerListener(undressDiv, this, 0);

            let setDivs = document.querySelectorAll("div[set_div_id]"); // Если setDivs.length = 0, то ничего не делаем - мы в заявке на бой
            if(setDivs.length > 0) {
                let lastSetNumber = 0;
                let i = 0;
                for(const setDiv of setDivs) {
                    let setNumber = setDiv.getAttribute("set_div_id");
                    if(setDiv.hasAttribute("onclick")) {
                        addSetChangerListener(setDiv, this, setNumber);
                        GM_setValue(userName + "weaponSet" + setNumber, setDiv.innerText);
                        lastSetNumber = ++i;
                    } else {
                        GM_deleteValue(userName + "weaponSet" + setNumber);
                    }
                }
                GM_setValue(userName + "LastSetNumber", lastSetNumber);
            }
        }
        this.findSetChangersAndAddListener();
    },
    findSetChangersAndAddListener: function() {
        let setRefs = document.querySelectorAll("a[href^='inventory.php?all_off=100']");
        for(const setRef of setRefs) {
            addSetChangerListener(setRef, this, 0);
        }
        setRefs = document.querySelectorAll("a[href*='inventory.php?all_on=']");
        for(const weaponSetReference of setRefs) {
            let setNumber = weaponSetReference.getAttribute("href").split("all_on=")[1];
            addSetChangerListener(weaponSetReference, this, setNumber);
        }
    }
};
/***********************************************************************************************************/
const skillSetsPreferences = {
    menuTitle: LocalizedString.Talents,
    setReferencePage: "skillwheel.php",
    sets: new Array(),
    menuItems: {},
    currentMenuItem: undefined,
    refreshingPages: "skillwheel.php;pl_info.php",

    getSets: function () {
        const setRefs = document.querySelectorAll("a[href^='skillwheel.php?setuserperk']");
        this.sets.length = 0;
        let i = 0;
        for(const setRef of setRefs) {
            this.sets.push({ number: i, name: setRef.innerHTML, method: "GET", url: setRef.href });
            addSetChangerListener(setRef, this, i);
            i++;
        }
    },
    getCurrentSetName: function() { return userName + currentFaction + "currentSkillSet"; }
};
/************************************************************************************************************/
const armySetsPreferences = {
    menuTitle: LocalizedString.Army,
    setReferencePage: "army.php",
    sets: new Array(),
    savedArmyInfos: new Array(),
    menuItems: {},
    currentMenuItem: undefined,
    savedSetIdsConst: "savedArmySetIds",
    savedSetConst: "savedArmySet",
    refreshingPages: "home.php;army.php;pl_info.php",
    setsTable: null,

    getSets: function () {
        this.sets.length = 0;
        let i = 0;
        for(const savedArmyInfo of this.savedArmyInfos) {
          let armySetTooltip = "";
            let postData = "";
            let j = 0;
            for(const armyUnitAmount of savedArmyInfo.army) {
                armySetTooltip += (armyUnitAmount == "" ? "0" : armyUnitAmount) + "+";
                postData = `countv${++j}=${(armyUnitAmount == "" ? "0" : armyUnitAmount)}${(postData == "" ? "" : "&") + postData}`;
            }
            this.sets.push({
                number: parseInt(savedArmyInfo.setId),
                name: savedArmyInfo.name,
                title: armySetTooltip.substring(0, armySetTooltip.length - 1),
                method: "POST",
                url: "army_apply.php",
                data: postData,
                contentType: "application/x-www-form-urlencoded"
            });
        }
    },
    getCurrentSetName: function() { return userName + currentFaction + "currentArmySet"; },
    init: function() {
        let savedSetIdsStr = GM_getValue(userName + currentFaction + this.savedSetIdsConst);
        let setIds = new Array();
        if(savedSetIdsStr) {
            setIds = savedSetIdsStr.split("|");
        }
        this.savedArmyInfos.length = 0;
        for(const setId of setIds) {
            if(setId == "") {
                continue;
            }
            let setStr = GM_getValue(userName + currentFaction + this.savedSetConst + setId);
            if(!setStr) {
                continue;
            }
            let savedSetParams = setStr.split("|");
            let savedArmyInfo = {
                setId: setId,
                name: savedSetParams[7],
                fraction: savedSetParams[8],
                army: new Array()
            };
            for(let j = 0; j < 7; j++) {
                savedArmyInfo.army[j] = savedSetParams[j];
            }
            this.savedArmyInfos.push(savedArmyInfo);
        }
        if(/\/army.php$/.test(location.href)) {
            this.drawSetsTable();
        }
    },
    drawSetsTable: function () {
        let div = addElement(elementType.center, document.querySelector("body"));
        addElement("br", div);
        this.setsTable = addElement(elementType.table, div, { bgcolor: "#959595", bordercolor: "#f5c137", border: "1px" });
        this.drawTableHeader();
        for(const savedArmyInfo of this.savedArmyInfos) {
            this.drawSetRow(savedArmyInfo);
        }
        let saveButton = addElement(elementType.input, div, { type: "button", value: LocalizedString.Save });
        saveButton.addEventListener("click", this.saveSets);
        let addButton = addElement(elementType.input, div, { type: "button", value: LocalizedString.Add });
        addButton.addEventListener("click", this.addSet);
        let addCurrentButton = addElement(elementType.input, div, { type: "button", value: LocalizedString.AddCurrent });
        addCurrentButton.addEventListener("click", this.addCurrentSet);
    },
    drawTableHeader: function () {
        if(!this.setsTable) {
            return;
        }
        let units = windowObject.obj;
        let tr = addElement("tr", this.setsTable);
        let th = addElement(elementType.td, tr);

        th.style.fontWeight = "bold";
        th.innerHTML = LocalizedString.SetName;
        for (let i = 1; i <= 7; i++) {
            th = addElement(elementType.td, tr);
            th.style.fontWeight = "bold";
            th.innerHTML = units[i]['name'];
        }
    },
    drawSetRow: function (savedArmyInfo) {
        if(!this.setsTable) {
            return;
        }
        let tr = addElement("tr", this.setsTable, { setId : savedArmyInfo.setId });
        let td = addElement(elementType.td, tr);
        let input = addElement(elementType.input, td, { value : savedArmyInfo.name, size : 22 });
        for(let i = 0; i < savedArmyInfo.army.length; i++) {
            td = addElement(elementType.td, tr);
            input = addElement(elementType.input, td, { value : savedArmyInfo.army[i], size : 5 });
        }
        td = addElement(elementType.td, tr);
        let delButton = addElement(elementType.input, td, { type : "button", value : "x", title : LocalizedString.Delete });
        delButton.addEventListener("click", this.deleteSet);
    },
    saveSets: function () {
        let table = armySetsPreferences.setsTable;
        let setIdsStr = "";
        for(let i = 1; i < table.rows.length; i++) {
            let setStr = "";
            let row = table.rows[i];
            let setId = row.getAttribute("setId");
            setIdsStr = setIdsStr + "|" + setId;
            for (let j = 1; j <= 7; j++) {
                setStr = setStr + "|" + row.cells[j].firstChild.value;
            }
            setStr = setStr + "|" + row.cells[0].firstChild.value + "|";
            setStr = setStr.substr(1);
            GM_setValue(userName + currentFaction + armySetsPreferences.savedSetConst + setId, setStr);
        }
        if(setIdsStr != "") {
            GM_setValue(userName + currentFaction + armySetsPreferences.savedSetIdsConst, setIdsStr.substr(1));
        } else {
            GM_deleteValue(userName + currentFaction + armySetsPreferences.savedSetIdsConst);
            GM_deleteValue(armySetsPreferences.getCurrentSetName());
        }
        let armySetIdRegExp = new RegExp(userName + currentFaction + armySetsPreferences.savedSetConst + '(\\d+)');
        let allStorageKeys = GM_listValues();
        let allStorageKeysCount = allStorageKeys.length;
        for(let i = allStorageKeysCount; i--; ) {
            let armySetId = armySetIdRegExp.exec(allStorageKeys[i]);
            if(armySetId && (setIdsStr == "" || !setIdsStr.match(armySetId[1])) ) {
                GM_deleteValue(allStorageKeys[i]);
            }
        }
    },
    addSet: function () {
        armySetsPreferences.drawSetRow({
            setId : (new Date()).getTime(),
            name : "",
            army : ["", "", "", "", "", "", ""]
        });
    },
    addCurrentSet: function () {
        let units = windowObject.obj;
        let army = {
            setId : (new Date()).getTime(),
            name : "",
            army : [units[1]['nownumberd'], units[2]['nownumberd'], units[3]['nownumberd'], units[4]['nownumberd'], units[5]['nownumberd'], units[6]['nownumberd'], units[7]['nownumberd']]
        };
        armySetsPreferences.drawSetRow(army);
    },
    deleteSet: function () {
        let table = this.parentNode.parentNode.parentNode;
        let row = this.parentNode.parentNode;
        table.removeChild(row);
    }
};
/************************************************************************************************************/
const factionsPreferences = {
    menuTitle: LocalizedString.Castle,
    setReferencePage: "castle.php",
    sets: new Array(),
    menuItems: {},
    currentMenuItem: undefined,
    availableCastleNames: "availableCastleNames",
    refreshingPages: "home.php;army.php;pl_info.php;castle.php;inventory.php;skillwheel.php",
    userCastleSign: undefined,
    userCastleSignName: "userCastleSign",
    refreshingConditions: function() {
        return false;
    },

    getSets: function() {
        let serializedCastlesInfo = GM_getValue(userName + this.availableCastleNames);
        if(serializedCastlesInfo) {
            let castles = serializedCastlesInfo.split("&");
            for(let i = 0; i < castles.length; i++) {
                let castleName = castles[i].split("=")[0];
                let castleNumber = castles[i].split("=")[1];
                this.sets[i] = { number: castleNumber, name: castleName, method: "GET" };
                if(this.userCastleSign) {
                    this.sets[i].url = "castle.php?change_clr_to=" + castleNumber + "&sign=" + this.userCastleSign;
                }
            }
        }
    },
    getCurrentSetName: function() { return userName + "currentCastle"; },
    init: function () {
        this.initCastlesList();
        this.userCastleSign = GM_getValue(userName + this.userCastleSignName);
        this.findSetChangersAndAddListener();
    },
    initCastlesList: function () {
        if(!/castle.php/.test(location.href)) {
            return;
        }
        let castleNamesDivs = document.querySelectorAll("div.castle_faction_div_inside");
        let serializedCastlesInfo = "";
        for(let castleNamesDivIndex = 0; castleNamesDivIndex < castleNamesDivs.length; castleNamesDivIndex++) {
            let castleNameDiv = castleNamesDivs[castleNamesDivIndex];
            let castleName = castleNameDiv.getAttribute("hint");
            let castleSelectRef = castleNameDiv.firstChild.getAttribute("href");
            let castleNumber = castleSelectRef.split("=")[1];
            serializedCastlesInfo = serializedCastlesInfo + (serializedCastlesInfo == "" ? "" : "&") + castleName + "=" + castleNumber;
        }
        GM_setValue(userName + this.availableCastleNames, serializedCastlesInfo);
        let castle_yes_no_dialogDiv = document.querySelector("div.castle_yes_no_dialog");
        if(castle_yes_no_dialogDiv) {
            let changeCastleRef = castle_yes_no_dialogDiv.querySelector("a[href*='castle.php?change_clr_to']");
            if(changeCastleRef) {
                let userCastleSign = changeCastleRef.getAttribute("href").split("?")[1].split("&")[1].split("=")[1];
                GM_setValue(userName + this.userCastleSignName, userCastleSign);
            }
        }
    },
    findSetChangersAndAddListener: function() {
        let setRefs = document.querySelectorAll("a[href*='castle.php?change_clr_to']");
        for(let i = 0; i < setRefs.length; i++) {
            let changeCastleRef = setRefs[i];
            let setNumber = changeCastleRef.getAttribute("href").split("?")[1].split("&")[0].split("=")[1];
            addSetChangerListener(changeCastleRef, this, setNumber);
        }
    },
    setChanged: function(newSetNumber) {
        currentFaction = "r" + newSetNumber + "_";
        GM_setValue(userName + "currentFaction", currentFaction);
        main();
    }
};

/************************************************************************************************************/
const preferences = [weaponSetsPreferences, skillSetsPreferences, armySetsPreferences, factionsPreferences];
var timer;
const menuId = "menuSetsTable";
const isNewInterface = document.querySelector("div.mm_item") ? true : false;

main();

function main() {
    console.log([userName, currentFaction]);
    if(document.querySelector("body") && userName && currentFaction) {
        if(isNewInterface) {
            createNewMenu();
        } else {
            createMenu();
        }
    }
}
function getMenuBaseElement() {
    if(isNewInterface) {
        return document.getElementById("MenuHome");
        return document.querySelector("div.mm_item");
    } else {
        let logobEngChild = document.querySelector("img[src*='logob_eng']") || document.querySelector("img[src*='logob_0eng_']") || document.querySelector("img[src*='23f_05']");
        if(logobEngChild) {
            return logobEngChild.parentNode;
        }
    }
}
function getTextWidth(text, font) {
  // re-use canvas object for better performance
  const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
  const context = canvas.getContext("2d");
  context.font = font;
  const metrics = context.measureText(text);
  return metrics.width;
}

function getCssStyle(element, prop) {
    return window.getComputedStyle(element, null).getPropertyValue(prop);
}

function getCanvasFont(el = document.body) {
  const fontWeight = getCssStyle(el, 'font-weight') || 'normal';
  const fontSize = getCssStyle(el, 'font-size') || '16px';
  const fontFamily = getCssStyle(el, 'font-family') || 'Times New Roman';

  return `${fontWeight} ${fontSize} ${fontFamily}`;
}
function createNewMenu() {
    let menuBaseElement = getMenuBaseElement();
    if(!menuBaseElement) {
        return;
    }
    let menuStyle = { borderColor : "#f5c137", background : "#4f76a7", color : "#f5c137", "z-index": (isPhotosPage ? "0" : "100") }
    if(document.querySelector("img[src*='i/top_ny']")) {
        menuStyle.background = "#003399";
    }
    let offSet = -194;

    let previousMainMenuItem = null;
    let menuPanel = document.querySelector("div.sh_MenuPanel");
    let i = 0;
    for(const currentPreferences of preferences) {
        if(currentPreferences.init) {
            currentPreferences.init();
        }
        currentPreferences.getSets();

        if(previousMainMenuItem) {
            offSet += previousMainMenuItem.clientWidth;
        }
        let menuHeaderStyle = {
            "font-size": "9pt",
            position: "absolute",
            "border-radius": "3px",
            height: "20px",
            width: "50px",
            margin: `${26}px 0px 0px ${offSet}px`,
            background: menuStyle.background,
            color: menuStyle.color,
            border: "1px solid " + menuStyle.borderColor,
            "font-weight": "bold",
            padding: "2px 6px 4px 5px",
            "z-index": menuStyle["z-index"]
        }
        let mainMenuItem = document.getElementById(menuId + i + "Header");
        let menuContent = document.getElementById(menuId + i);
        if(!mainMenuItem) {
            mainMenuItem = createElement(elementType.div, { id: menuId + i + "Header" }, menuHeaderStyle); // , "class": "mm_item mm_item_blue" , style: `position: absolute; display: table; top: ${menuPanel.style.top}; left: ${offSet}; height: 20px; width: 60px; z-index: 100;`
            if(previousMainMenuItem) {
                previousMainMenuItem.after(mainMenuItem);
            } else {
                menuPanel.insertBefore(mainMenuItem, menuBaseElement.parentNode.parentNode);
            }
            let setReferencePage = addElement(elementType.a, mainMenuItem, { innerHTML: currentPreferences.menuTitle, href: currentPreferences.setReferencePage, style: `color: ${menuStyle.color}; text-decoration: none;` });

            let div1 = addElement(elementType.a, mainMenuItem, { innerHTML: "", href: "javascript:void(0)", style: `color: ${menuStyle.color}; text-decoration: none; vertical-align: middle;` });

            menuContent = addElement(elementType.div, div1, { id: menuId + i, style: `position: relative; margin-top: 10px;background: ${menuStyle.background}; padding: 6px 3px 2px 3px; white-space: nowrap; z-index: ${menuStyle["z-index"]};` }); // , "class": "sh_dd_container"
            mainMenuItem.addEventListener("mouseenter", function() { timer = setTimeout(function () { menuContent.style.display = "block"; }, 100); }, false);
            mainMenuItem.addEventListener("mouseleave", function() { clearTimeout(timer); menuContent.style.display = "none"; }, false);
            menuContent.addEventListener("mouseenter", function() { menuContent.style.display = "block"; }, false);
            menuContent.addEventListener("mouseleave", function() { clearTimeout(timer); menuContent.style.display = "none"; }, false);
        } else {
            menuContent.innerHTML = '';
        }
        previousMainMenuItem = mainMenuItem;

        menuContent.style.display = "block"; // Перед заполнением покажем див для правильного определения его размеров (нужно, если он установлен в none)
        let currentSetNumber = GM_getValue(currentPreferences.getCurrentSetName(), -1);
        let maxClientWidth = menuContent.clientWidth;
        for(const currentSet of currentPreferences.sets) {
            if(!currentSet) {
                continue;
            }
            let dropDownMenuItem = addElement(isPhotosPage ? elementType.div : elementType.li, menuContent, { type: "disc", style: "text-align: left;" });
            let currentSetReference = addElement("b", dropDownMenuItem, { innerHTML: currentSet.name, title: currentSet.title || "", style: `color: ${menuStyle.color}; cursor: pointer;` });
            if(currentSet.url) {
                currentSetReference.addEventListener("click", function() { applySet(currentSetReference, currentPreferences, currentSet); }, false);
            }
            if(currentSet.number == currentSetNumber) {
                markCurrent(currentSetReference, currentPreferences, currentSet.number);
            }
            currentPreferences.menuItems[currentSet.number] = currentSetReference;

            let currentWidth = getTextWidth(currentSet.name, getCanvasFont(currentSetReference));
            if(maxClientWidth < currentWidth) {
                maxClientWidth = currentWidth;
            }
        }
        menuContent.style.width = `${(maxClientWidth + 15)}px`;
        menuContent.style.display = "none";
        i++;
    }
}
function createMenu() {
    let menuBaseElement = getMenuBaseElement();
    console.log(menuBaseElement);
    if(!menuBaseElement) {
        return;
    }
    let menuStyle = { borderColor : "#f5c137", background : "#6b6b69", color : "#f5c137", "z-index": "100" }
    if(document.querySelector("img[src*='i/top_ny']")) {
        menuStyle.background = "#003399";
    }
    let offSet = -80;

    let previousMainMenuItem = null;
    let i = 0;
    for(const currentPreferences of preferences) {
        if(currentPreferences.init) {
            currentPreferences.init();
        }
        currentPreferences.getSets();

        if(previousMainMenuItem) {
            offSet += previousMainMenuItem.clientWidth;
        }
        let menuHeaderStyle = {
            position: "absolute",
            "border-radius": "3px",
            margin: "2px 0px 0px " + offSet + "px",
            background: menuStyle.background,
            color: menuStyle.color,
            border: "1px solid " + menuStyle.borderColor,
            "font-weight": "bold",
            padding: "2px 6px 4px 5px",
            "z-index": (isPhotosPage ? "0" : "100")
        }
        let mainMenuItem = document.getElementById(menuId + i + "Header");
        let menuContent = document.getElementById(menuId + i);
        if(!mainMenuItem) {
            mainMenuItem = addElement(elementType.div, menuBaseElement, { id: menuId + i + "Header" }, menuHeaderStyle);
            addElement(elementType.a, mainMenuItem, { innerHTML: currentPreferences.menuTitle, href: currentPreferences.setReferencePage, style: `color: ${menuStyle.color}; text-decoration: none;` });

            menuContent = addElement(elementType.div, mainMenuItem, { id: menuId + i, style: "position: relative; padding: 6px 3px 2px 3px; white-space: nowrap;" });
            mainMenuItem.addEventListener("mouseover", function() { timer = setTimeout(function () { menuContent.style.display = "block"; }, 100); }, false);
            mainMenuItem.addEventListener("mouseout", function() { clearTimeout(timer); menuContent.style.display = "none"; }, false);
            menuContent.addEventListener("mouseover", function() { menuContent.style.display = "block"; }, false);
            menuContent.addEventListener("mouseout", function() { clearTimeout(timer); menuContent.style.display = "none"; }, false);
        } else {
            menuContent.innerHTML = '';
        }
        previousMainMenuItem = mainMenuItem;

        menuContent.style.display = "block"; // Перед заполнением покажем див для правильного определения его размеров (нужно, если он установлен в none)
        let currentSetNumber = GM_getValue(currentPreferences.getCurrentSetName(), -1);
        let maxClientWidth = menuContent.clientWidth;
        for(const currentSet of currentPreferences.sets) {
            if(!currentSet) {
                continue;
            }
            let dropDownMenuItem = addElement(isPhotosPage ? elementType.div : elementType.li, menuContent, { type: "disc", style: "text-align: left;" });
            let currentSetReference = addElement("b", dropDownMenuItem, { innerHTML: currentSet.name, title: currentSet.title || "", style: `color: ${menuStyle.color}; cursor: pointer;` });
            if(currentSet.url) {
                currentSetReference.addEventListener("click", function() { applySet(currentSetReference, currentPreferences, currentSet); }, false);
            }
            if(currentSet.number == currentSetNumber) {
                markCurrent(currentSetReference, currentPreferences, currentSet.number);
            }
            currentPreferences.menuItems[currentSet.number] = currentSetReference;

            let currentWidth = getTextWidth(currentSet.name, getCanvasFont(currentSetReference));
            if(maxClientWidth < currentWidth) {
                maxClientWidth = currentWidth;
            }
        }
        //menuContent.style.width = `${(menuContent.clientWidth + 20)}px`;
        menuContent.style.display = "none";
        i++;
    }
}
function markCurrent(el, currentPreferences, currentSetNumber) {
    GM_setValue(currentPreferences.getCurrentSetName(), currentSetNumber);
    el.style.color = '#0f0';
    if (currentPreferences.currentMenuItem && currentPreferences.currentMenuItem != el) {
        currentPreferences.currentMenuItem.style.color = "#f5c137";
    }
    currentPreferences.currentMenuItem = el;
}
function addSetChangerListener(htmlElement, currentPreferences, setNumber) {
    htmlElement.addEventListener("click", function() { markCurrent(currentPreferences.menuItems[setNumber], currentPreferences, setNumber); }, false);
}
function applySet(selectedElement, currentPreferences, currentSet) {
    markCurrent(selectedElement, currentPreferences, currentSet.number);
    let originalText = selectedElement.innerHTML;
    selectedElement.innerHTML += " " + getLoadGif();
    let objXMLHttpReqSM = new XMLHttpRequest();
    objXMLHttpReqSM.open(currentSet.method, currentSet.url, true);
    objXMLHttpReqSM.onreadystatechange = function () {
        if (objXMLHttpReqSM.readyState == 2) {
            objXMLHttpReqSM.abort();
            selectedElement.innerHTML = originalText;
            if(typeof(currentPreferences.setChanged) == "function") {
                currentPreferences.setChanged(currentSet.number);
            }
            if(currentPreferences.refreshingPages) {
                let pages = currentPreferences.refreshingPages.split(';');
                for(const page of pages) {
                    if(location.href.indexOf(page) > -1) {
                        console.log(page);
                        window.location.reload(); //window.location.href = window.location.href;
                    }
                }
            }
            if(currentPreferences.refreshingConditions && currentPreferences.refreshingConditions()) {
                window.location.reload(); // window.location.href = window.location.href;
            }
        }
    };
    if(currentSet.contentType) {
        objXMLHttpReqSM.setRequestHeader('Content-type', currentSet.contentType);
    }
    objXMLHttpReqSM.send(currentSet.data);
    return false;
}
function addElement(type, parent, data, style) {
    let el = createElement(type, data, style);
    if(parent) {
        parent.appendChild(el);
    }
    return el;
}
function createElement(type, data, style) {
    let el = document.createElement(type);
    if(data) {
        for(const key in data) {
            if(key == "innerHTML") {
                el.innerHTML = data[key];
            } else {
                el.setAttribute(key, data[key]);
            }
        }
    }
    if(style && el.id) {
        let styleStr = "";
        if(typeof(style) == "string") {
            styleStr = style;
        } else {
            for (let key in style) {
                styleStr += key + ": " + style[key] + "; ";
            }
        }
        GM_addStyle("#" + el.id + "{" + styleStr + "}");
    }
    return el;
}
function getLoadGif() {
    return '<img border="0" align="absmiddle" height="11" src="data:image/gif;base64,' +
    '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' +
    'fySDhGYQdDWGQyUhADs=">';
}
function ensureGmMethods() {
    if(!this.GM_getValue) {
        this.GM_getValue = function(key, def) {
            return localStorage[key] || def;
        };
        this.GM_setValue = function(key, value) {
            localStorage[key] = value;
        };
        this.GM_deleteValue = function(key) {
            return delete localStorage[key];
        };
    }
    if(!this.GM_addStyle) {
        this.GM_addStyle = function(key) {
            let style = document.createElement('style');
            style.type = "text/css";
            style.textContent = key;
            document.querySelector("head").appendChild(style);
        }
    }
    if(!this.GM_listValues) {
        this.GM_listValues = function() {
            let values = [];
            for (let i = 0; i < localStorage.length; i++) {
                values.push(localStorage.key(i));
            }
            return values;
        }
    }
}
function CalculateUserNameAndFaction() {
    let enterButton = document.querySelector("input[src$='" + LocalizedString.EnterJpg + "']");
    if(/login.php$/.test(location.href)) {
        enterButton = document.querySelector("input[value='" + LocalizedString.SignInTitle + "']");
    }
    let loginTextBox = document.querySelector("input[name='login']");
    if(enterButton && loginTextBox) {
        enterButton.addEventListener("click", function() { GM_setValue("UserName", loginTextBox.value + "_"); })
    } else {
        userName = GM_getValue("UserName");
        if(!userName) {
            return;
        }
        userName = encodeURIComponent(userName);
        let currentFactionNumber = undefined;
        if(location.pathname == '/home.php') {
            // for new home page
            let currentFactionIconContainer = document.querySelector("div.home_css_pl_fract.show_hint");
            if(!currentFactionIconContainer) {
                currentFactionIconContainer = document.querySelector("a[href^='castle.php?change_faction_dialog']");
            }
            if(currentFactionIconContainer) {
                let currentFactionIconImg = currentFactionIconContainer.querySelector("img");
                currentFactionNumber = currentFactionIconImg.src.split("i/f/r")[1].split(".png")[0];
            }
        } else if(location.pathname=='/pl_info.php') {
            let temp_nick = userName;
            let temp_regexp = new RegExp(temp_nick.slice(0, -1)+'.\{30,150\}\\/i\\/f\\/(r\\d+)\\.png');
            let frakPng = temp_regexp.exec( document.querySelector("body").innerHTML );
            if(frakPng) {
                currentFactionNumber = frakPng[1].substring(1);
            }
        } else if(location.pathname=='/castle.php') {
            let selectedFactionImg = document.querySelector("div.castle_faction_div_inside2 img");
            let selectedFactionImgName = selectedFactionImg.getAttribute("src");
            let selectedFactionNumber = selectedFactionImgName.split("kukla_png/kukla")[1].split(".")[0]; //dcdn.heroeswm.ru/i/kukla_png/kukla5.png

            let faction_listDiv = document.querySelector("div[id='faction_list']");
            if(faction_listDiv.getAttribute("style").includes("display:none;")) {
                currentFactionNumber = selectedFactionNumber;
            }
        }
        if(currentFactionNumber) {
            GM_setValue(userName + "currentCastle", currentFactionNumber);
            GM_setValue(userName + "currentFaction", "r" + currentFactionNumber + "_");
        }
        currentFaction = GM_getValue(userName + "currentFaction");
    }
}
function uchar(s) {
    switch (s[0]) {case "А": return "\u0410"; case "Б": return "\u0411"; case "В": return "\u0412"; case "Г": return "\u0413"; case "Д": return "\u0414"; case "Е": return "\u0415"; case "Ж": return "\u0416"; case "З": return "\u0417"; case "И": return "\u0418"; case "Й": return "\u0419"; case "К": return "\u041a"; case "Л": return "\u041b"; case "М": return "\u041c"; case "Н": return "\u041d"; case "О": return "\u041e"; case "П": return "\u041f"; case "Р": return "\u0420"; case "С": return "\u0421"; case "Т": return "\u0422"; case "У": return "\u0423"; case "Ф": return "\u0424"; case "Х": return "\u0425"; case "Ц": return "\u0426"; case "Ч": return "\u0427"; case "Ш": return "\u0428"; case "Щ": return "\u0429"; case "Ъ": return "\u042a"; case "Ы": return "\u042b"; case "Ь": return "\u042c"; case "Э": return "\u042d"; case "Ю": return "\u042e"; case "Я": return "\u042f"; case "а": return "\u0430"; case "б": return "\u0431"; case "в": return "\u0432"; case "г": return "\u0433"; case "д": return "\u0434"; case "е": return "\u0435"; case "ж": return "\u0436"; case "з": return "\u0437"; case "и": return "\u0438"; case "й": return "\u0439"; case "к": return "\u043a"; case "л": return "\u043b"; case "м": return "\u043c"; case "н": return "\u043d"; case "о": return "\u043e"; case "п": return "\u043f"; case "р": return "\u0440"; case "с": return "\u0441"; case "т": return "\u0442"; case "у": return "\u0443"; case "ф": return "\u0444"; case "х": return "\u0445"; case "ц": return "\u0446"; case "ч": return "\u0447"; case "ш": return "\u0448"; case "щ": return "\u0449"; case "ъ": return "\u044a"; case "ы": return "\u044b"; case "ь": return "\u044c"; case "э": return "\u044d"; case "ю": return "\u044e"; case "я": return "\u044f"; case "Ё": return "\u0401"; case "ё": return "\u0451"; default: return s[0];}}
function ustring(s) {
    s = String(s);
    let result = "";
    for(let i = 0; i < s.length; i++) {
        result += uchar(s[i]);
    }
    return result;
}

})();