HWM_auction_upd

Обновленный рынок

目前為 2021-11-02 提交的版本,檢視 最新版本

// ==UserScript==
// @name              HWM_auction_upd
// @author            Мифист
// @namespace         Мифист
// @description       Обновленный рынок
// @homepage          https://gf.qytechs.cn/ru/users/687755-мифист
// @icon              https://dcdn.heroeswm.ru/hwmicon.ico
// @version           1.0
// @encoding          utf-8
// @include           https://*heroeswm.ru/auction.php*
// @include           https://*lordswm.com/auction.php*
// @include           http://*178.248.235.15/auction.php*
// @connect           gf.qytechs.cn
// @require           https://gf.qytechs.cn/scripts/433008-hwm-all-arts/code/HWM_all_arts.js?version=984720
// @run-at            document-start
// @grant             none
// @noframes
// ==/UserScript==

(function() {
  'use strict';

  const $ = (() => { let regId = /[\s.,:>+~\[]/; function $(e, context) { if (!e) return null; if (e.nodeType) return e; if (context && typeof context === 'string') context = $(context); return context === null ? null : (!context && e[0] === '#' && !regId.test(e)) ? document.getElementById(e.slice(1)) : (context || document).querySelector(e); } function extend(target, source) { for (let key in source) { target[key] = source[key]; } return target; } return extend($, { extend: extend, index(e) { return $.toArray(e.parentNode.children).indexOf(e); }, toArray(obj) { let j = obj.length, result = new Array(j); while (j--) result[j] = obj[j]; return result; }, parseNode(html, callback) { let div = document.createElement('div'); div.innerHTML = html; div = div.firstChild.cloneNode(true); callback && callback.call(div); return div; } }); })();
  const $$ = (selector, context) => { context = context && $(context); return context === null ? [] : $.toArray((context || document).querySelectorAll(selector)); }

  function getSearchParams(search) {
    const entries = [...new URLSearchParams(search).entries()];

    return !entries.length ? null : Object.fromEntries(entries);
  }

  function appendAuc() {
    !aucElem.parentNode && document.body.prepend(aucElem);
  }

  const version = '1.0';
  const plid = document.cookie.match(/pl_id=(\d+)/)[1];
  const betsData = JSON.parse(localStorage[`newAucBets_${plid}`] || '{}');
  const chosenList = JSON.parse(localStorage[`newAucChosen_${plid}`] || '[]');
  const settings = (() => {
    const key = `newAucSettings_${plid}`;
    const that = JSON.parse(localStorage[key] || 'null') || ({
      playerName: '',
      sort: 'byCost',
      order: '1',
      timers: true,
      extSearch: false,
      filters: { full: 1 }
    });

    return Object.defineProperty(that, 'update', {
      value: (k, v) => {
        that[k] = v == null ? null : v;
        localStorage[key] = JSON.stringify(that);

        return that;
      }
    });
  })();

  $.parseNode('<style class="auc_css" id="hwm_css"></style>', function() {
    this.textContent = 'body { background-color: #353741 !important; background-image: linear-gradient(45deg, black, transparent) !important; overflow: hidden !important; } body > :not(#auction) { display: none; }';
    document.head.append(this);
  });

  $.parseNode('<style class="auc_css" id="auc_css"></style>', function() {
    this.textContent = '@charset "utf-8";/* ------ reboot ------ */:before,:after {box-sizing: border-box;}:root {font-size: 10px;}button {cursor: pointer;}img {max-width: 100%;vertical-align: middle;pointer-events: none;}main * {font-family: inherit;font-size: inherit;margin: 0;padding: 0;box-sizing: border-box;}main a,main button,main input {color: inherit;border: none;outline: none;text-decoration: none;}/* ------------------ */@keyframes spin {100% {transform: rotate(1turn);}}.ui-scroll {overflow-x: hidden;overflow-y: auto;scrollbar-width: thin;}.ui-scroll::-webkit-scrollbar {width: .5rem;background-color: #696969;}.ui-scroll::-webkit-scrollbar-thumb {min-height: 4rem;background-color: #aaa;}[href*="auction.php"]:hover {color: #cfbba0;}/* === AUCTION === */#auction {font-family: Arial, sans-serif;font-size: 1.6rem;width: 100%;min-width: 96rem;height: 100vh;min-height: 60rem;position: fixed;left: 0; top: 0;color: #eee;background-color: #494751;box-sizing: border-box;user-select: none;z-index: 900;}.__loading::after,.__progress::after {content: "";position: absolute;left: 5rem; right: 0; top: 5rem; bottom: 0;background-color: #3c4a57;opacity: .3;z-index: 100;}#auction__header {height: 5rem;line-height: 5rem;position: relative;padding: 0 .6em;border-bottom: .1rem solid #1a1a1a;z-index: 2;}#refresh {font-size: 1.3em;letter-spacing: .5rem;text-transform: uppercase;filter: drop-shadow(.2rem .2rem .2rem black);}#refresh:hover {filter: sepia(1) drop-shadow(.2rem .2rem .2rem black);}@supports ((background-clip: text) or (-webkit-background-clip: text)) {@keyframes aucBg {100% {background-position: -150%;}}#refresh {color: transparent;background-clip: text;-webkit-background-clip: text;background-image: linear-gradient(45deg, #00bfff, #64cccc, #8ed8ab, #f5e275, #8ed8ab, #64cccc, #00bfff);background-size: 300%;animation: aucBg 4s ease-in-out infinite;}}#author {margin-left: 1rem;color: #aaa;}#author:hover {color: tan;}#author::before {content: "© ";color: #aaa;}/* resources */#resources {float: right;overflow: hidden;}.res__item {float: left;margin-left: 1.4rem;}.res__item::after {content: attr(data-value);}#res-gold::after {color: gold;}/* menu block */#auction__container {height: calc(100% - 5rem);display: flex;}#aside_1 {width: 5rem;min-width: 5rem;height: 100%;position: relative;color: #ddd;}.menu:hover {background-color: #222;background-image: linear-gradient(45deg, transparent, #25334a);outline: .1rem solid #666;}.menu__link {display: block;padding: .5rem 0;}.menu__icon {width: 100%;filter: saturate(.5);}.menu:hover .menu__icon {filter: saturate(1);}.menu__list {width: 26.8rem;height: calc(100% - 5rem);position: absolute;left: 100%; top: 0;margin-left: .1rem;background-color: #2d2c33;visibility: hidden;z-index: 40;}.menu:hover .menu__list {visibility: visible;}.menu__list::before {content: "# " attr(data-name);display: block;padding: 1rem;text-transform: uppercase;color: tan;border-bottom: 1px solid #444;}.menu__list::after {content: "";width: .2rem;position: absolute;left: -.1rem; top: 0; bottom: 0;}.menu__item {display: block;padding: .8rem 1.2rem;border-bottom: 1px solid #444;}.menu__item.__red {color: lightcoral;}.menu__item:hover {color: #cfbba0;background-image: linear-gradient(45deg, #222, #25334a, transparent);}/* player */#aside_2 {width: 27rem;min-width: 27rem;height: 100%;position: relative;background-color: #2d2c33;border-left: .1rem solid #555;border-right: .1rem solid #444;overflow: hidden;z-index: 20;}#player {height: 8rem;line-height: 3.5rem;padding-left: 1rem;}#player__name {color: tan;}#player__name:hover {filter: saturate(1.2) brightness(1.2);}.gold {vertical-align: middle;}#player__gold {font-size: 1.2em;color: gold;}#player__name:empty::before,#player__gold:empty::before {content: "...";}.coin {font-family: sans-serif;font-size: 1.2rem;width: 1.5em;line-height: 1.5em;display: inline-block;vertical-align: middle;margin-left: .5em;text-align: center;color: #927008;background-color: #ffcc33;border-radius: 50%;box-shadow: inset 0 0 0 .2em #c79600;}#coin {font-size: 2rem;position: relative;margin-left: 0;margin-right: .4em;background-image: linear-gradient(145deg, #ffc001, #ffd900, #cc9900);}#coin::before {content: "";position: absolute;left: 0; right: 0; top: 0; bottom: 0;margin: .1em;border: .1em solid #917317;border-radius: inherit;}/* categories */#categories {height: calc(100% - 13rem);display: flex;flex-direction: column;color: #aaa;background-color: #313038;border-top: .1rem solid #444;}.category.__active {color: #eee;background-color: #2b3a4c75;}.category.__active,.category__heading {border-bottom: .1rem solid #444;}.category__heading {height: 3.4rem;line-height: 3.4rem;font-weight: inherit;position: relative;top: 0;padding: 0 2rem 0 .3rem;cursor: pointer;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;z-index: 2;}.category__heading:hover {background-color: #33405175;}.category.__active .category__heading {position: sticky;background-color: #3c4754;}.category__heading::after {content: "▼";font-size: .6em;position: absolute;top: 0; right: 1rem;opacity: .7;}.category.__active .category__heading::after {content: "▲";}.category__items {font-size: .9em;max-height: 0;overflow: hidden;transition: max-height .5s;}.category__item {height: 2.8rem;line-height: 2.7rem;display: block;padding: 0 1rem;color: #a0b1bb;border-top: .1rem solid #495055;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}.category__item:first-child {border-top: none;}.category__item:hover {background-color: #3f4b5a75;}.category__item::before {content: "•";margin-right: .8rem;color: #aaa;}.category__all {font-size: .8em;min-width: 3.5rem;display: inline-block;text-align: center;color: #d1bfa8;pointer-events: auto;}.category__all:hover {color: #94d4da;}.category__img {margin-right: .5em;}#cat-res,#cat-elements {order: -1;}#cat-my .category__heading {pointer-events: none;}#cat-my .category__heading::after {display: none;}#new-lot {height: 5rem;line-height: 5rem;text-align: center;color: #aaa;border-top: .1rem solid #444;}#new-lot__link {color: #d1bfa8;}#new-lot__link:hover {text-decoration: underline;}/* main */#main {flex: 1;width: calc(100% - 32rem);min-width: 86rem;height: 100%;display: flex;flex-direction: column;position: relative;background-color: #201f24;counter-reset: lot;}.main__top {height: 5rem;display: flex;justify-content: flex-start;align-items: center;padding: .7rem;}.main__top:first-child {background-color: #2b2b33;border-bottom: .1rem solid #444;}.a-box {width: 20rem;height: 100%;position: relative;margin-right: 1rem;background-color: #3a404e;box-shadow: 0 0 .3rem #000;}.a-box:last-child {margin-right: 0;margin-left: auto;}.a-box::after {content: "";height: .4rem;position: absolute;left: 0; right: 0; top: 100%;}.a-btn {width: 100%;height: 100%;background-color: transparent;}.a-btn:focus {outline: .2rem solid #57d6cf5b;outline-offset: -.3rem;}.a-btn::before {content: "";width: 1.6rem;height: 1.6rem;display: inline-block;vertical-align: middle;margin-right: .8rem;background: center / contain;filter: sepia(1) brightness(2);}.main__top:nth-child(2) .a-btn::before {display: none;}#artlist-btn {text-indent: -2rem;}#artlist-btn::before {background-image: url("https://dcdn.heroeswm.ru/i/help/help_ico11.png");}#setlist-btn::before {background-image: url("https://dcdn.heroeswm.ru/i/help/help_ico40.png");}#chosen-btn::before {background-image: url("https://dcdn3.heroeswm.ru/i/pl_info/services/icon_Clans.png");}#artlist-eye {width: 2rem;height: 2rem;position: absolute;right: 1rem; top: calc(50% - 1rem);fill: currentColor;color: gray;cursor: pointer;}#artlist-eye.__switch-on {color: #a2c5cd;}.a-list {min-width: 100%;max-width: 28rem;max-height: 35rem;line-height: 2;position: absolute;top: calc(100% + 2rem); left: 0;margin-top: .4rem;background-color: #41414b;border: .1rem solid #555;box-shadow: .2rem .2rem .4rem #161616;opacity: 0;visibility: hidden;pointer-events: none;transition: top .3s .2s, opacity .3s .2s, visibility .3s .2s;z-index: 910;}.a-list:empty {display: none;}.a-box:hover .a-list,:focus + .a-list,.__active ~ #chosen {top: 100%;opacity: 1;visibility: visible;pointer-events: auto;}.a-box:hover .a-list {z-index: 920;}.a-list__item {display: block;padding: 0 1rem;color: #bbb;border-bottom: .1rem solid #555;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}.a-list__item:first-child {border-top: .1rem solid #555;}.a-list__item:hover {background-color: #36363f;}.a-list::before,.a-list::after {content: "";height: 1.4rem;display: block;position: sticky;top: 0;background: linear-gradient(#41414b 30%, transparent);pointer-events: none;z-index: 2;}.a-list::after {top: auto; bottom: 0;transform: scaleY(-1);}.a-box .__left {width: calc(100% - 4rem);float: left;}.a-link__img {width: 2.5rem;margin: 0 1rem 0 -.5rem;}/* setlist */.setlist__set {border-top: .1rem solid #555;}.setlist__set:last-child {border-bottom: .1rem solid #555;}.setlist__set-name {font-weight: inherit;padding: 0 2.5rem 0 1rem;background-color: #3c3c45;white-space: nowrap;}.setlist__set-name:hover {filter: saturate(1.2) brightness(1.2);}.setlist__set-name::before {content: "@ сет";margin-right: .5em;color: #c9bba8;}.setlist__set-name::after {content: "+";position: absolute;right: 1rem;color: #aaa;}.setlist__set.__active .setlist__set-name::after {content: "-";}.setlist__arts {max-height: 0;text-indent: 1rem;overflow: hidden;}.setlist__set.__active .setlist__arts {max-height: none;}.setlist__arts:empty::before {content: "Нет на рынке";display: block;padding-left: 1rem;color: #f0b1b1;border-top: .1rem solid #555;}.setlist__arts :last-child {border-bottom: none;}/* search */#search-box {width: 26rem;box-shadow: none;}.a-input {height: 100%;padding: 0 3rem 0 .6rem;color: lightblue;background-color: #1a1a1a;box-shadow: inset -.1rem -.1rem .1rem #555;user-select: auto;}.a-input:focus {box-shadow: inset 0 0 .2rem #57d6cf;}#search:invalid {color: lightcoral;box-shadow: inset 0 0 .2rem .1rem;}.action {width: 4rem;height: 100%;float: right;color: #bbb;background-color: #344259;outline: .2rem solid #646363;outline-offset: -.3rem;}.action:hover {background-color: #3f4e67;}.action:active {transform: scale(.9);}.action.__active {color: #83add4;outline-color: #57d6cf5b;}#ext-search {font-size: .8em;}#search-reset {font-size: 1.6em;width: 3rem;line-height: 3.4rem;position: absolute;right: 4rem; top: 0;color: #bbb;text-align: center;cursor: pointer;visibility: hidden;}#search-reset:hover {color: inherit;}#search-reset.__shown {visibility: visible;}#select-link {position: relative;color: #d3ad7b;background-color: #31313c;z-index: 2;}/* chosen */.__empty #chosen-btn {background-color: #666;text-decoration: line-through;pointer-events: none;opacity: .5;}#chosen {left: auto; right: 0;}.chosen__item {position: relative;padding: 0;}.chosen__link {display: block;padding-left: 1rem;padding-right: 3rem;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}[data-chosen-action="remove"] {position: absolute;right: 0; top: 0;padding: 0 1rem;color: #eee;visibility: hidden;}[data-chosen-action="remove"]:hover {color: #fa9696;}.chosen__item:hover [data-chosen-action="remove"] {visibility: visible;cursor: pointer;}#chosen-input-box {width: 26rem;height: 100%;position: absolute;top: 0; right: calc(100% + 1rem);visibility: hidden;z-index: 10;}.__active ~ #chosen-input-box {visibility: visible;}/* filters */#filters-box {counter-reset: filter;}#filters-icon {vertical-align: middle;margin-right: .8rem;fill: currentColor;color: wheat;}#filters-box.__disabled,#filters-box.__disabled #filters-icon {color: gray;filter: grayscale(.7);pointer-events: none;}#filters-counter {position: absolute;left: calc(100% + 1rem); top: 1rem;color: #aaa;pointer-events: none;}#filters-counter::after {content: counter(filter);}#filters {min-width: 24rem;white-space: nowrap;}.filters__group {display: flex;border-bottom: .1rem solid #5a5a5a;}.filters__group:first-child {border-top: .1rem solid #5a5a5a;}.filters__item {width: 50%;padding: 0 1rem;color: #bbb;}.filters__item:hover {background-color: #36363f;}.filters__item:first-child {border-right: .1rem solid #5a5a5a;}.filters__item.__active {counter-increment: filter;color: #cfbba0;background-color: #424b5d;}.__partial .filters__group:nth-child(n+2) .filters__item {counter-increment: none;color: #6e6e6e;background-color: transparent;pointer-events: none;}/* sorts */#sorts {height: 4rem;display: flex;padding-right: .5rem;margin-top: 1rem;color: #aaa;background-color: #2e2d36;border: .1rem solid #41434a;border-width: .1rem 0;overflow: hidden;}.a-td {width: calc(100% - 32rem);min-width: 10rem;height: 100%;display: flex;flex-direction: column;justify-content: space-evenly;align-items: center;text-align: center;padding: 0 .5rem;border-right: .1rem solid #41434a;overflow: hidden;}.a-td:last-child {border-right: none;}._name {min-width: 32rem;padding-left: 0;}._name,.sorts__item {flex-direction: row;justify-content: center;}.sorts__item:hover {color: #81b0d8;cursor: pointer;}.sorts__item[data-order]::after {content: "▲";font-size: .7em;width: 0;display: inline-block;position: relative;left: .8rem;color: #aaa;}.sorts__item[data-order="0"]::after {content: "▼";}/* lot */#lots-container {flex: 1;position: relative;}#lots-container::before {content: "Лотов не найдено, мяу ^_^";line-height: 2;position: absolute;left: 0; right: 0;padding: 1em;text-align: center;color: #bbb;border-bottom: .1rem solid #333;}#lots {width: 100%;display: flex;flex-direction: column;justify-content: flex-start;position: relative;background-color: #201f24;border-bottom: .1rem solid #3c3e46;overflow: hidden;}#lots[data-order="0"] {flex-direction: column-reverse;}.lot {font-size: .9em;height: 8.5rem;display: flex;justify-content: space-between;position: relative;color: #ddd;border-top: .1rem solid #3c3e46;overflow: hidden;counter-increment: lot;}[data-cat="obj_share"] {height: 11rem;}.lot:nth-child(even) {background-color: #22242c;}.lot:hover {background-image: linear-gradient(to right, #3a2727cc, transparent);}.lot[data-params*="mybet=1"] {background-color: #34504d3d;}[data-params*="mybet=1"]:nth-child(even) {background-color: #34504559;}.lot[data-params*="selled=1"] {color: #aaa;background-color: #3339;filter: grayscale(1) opacity(.8);pointer-events: none;}.lot[data-params*="mylot=1"] {display: flex;order: -1;background-color: #2c3b5ab2;}[data-params*="mylot=1"]:nth-child(even) {background-color: #28364eb2;}[data-params*="once=0"][data-params*="mylot=1"] {filter: grayscale(.3);pointer-events: none;}.lot.__target {display: flex;order: -2;background-color: #7656a433;box-shadow: inset 0 0 .4rem #b63ab7;z-index: 2;}#lots[data-order="0"] [data-params*="mylot=1"] {order: 1;}#lots[data-order="0"] .lot.__target {order: 2;}.lot.__active {background-image: linear-gradient(to right, #33485fcc, transparent);outline: .2rem solid #4e8fb8;outline-offset: .1rem;z-index: 4;}.lot__box {min-width: 8.4rem;height: 100%;display: block;position: relative;color: inherit !important;}.lot__img {width: 5rem;display: block;position: absolute;left: 0; right: 0; top: 0; bottom: 0;margin: auto;}.with-info,.lot__amount {position: absolute;right: .2rem; bottom: .2rem;pointer-events: none;}.with-info {font-family: serif;font-size: 1.4em;top: .2rem; bottom: auto;opacity: .6;}.lot__info {width: calc(100% - 7rem);height: 100%;padding: 0 .8rem;display: flex;flex-direction: column;justify-content: space-evenly;align-items: flex-start;overflow: hidden;text-align: left;}.lot__id {color: #aaa;}.lot__id::before {content: "#";color: #c9bba8;}.lot__name {max-width: 100%;color: #dda94a;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}.lot__durability {letter-spacing: .1rem;}.lot__durability::before {content: "Прочность: ";letter-spacing: normal;color: #ccc;}[data-cat="part"] .lot__durability::before {content: "Частей: ";}[data-cat="part"] .lot__durability font {color: inherit;}.mods-scope {color: #ccc;}.mods-scope::before {content: "Крафт: [ ";}.mods-scope::after {content: " ]";}.art-mods {width: .8rem;position: absolute;left: .5rem; top: 1rem;z-index: 1;}.art-mods img {width: 100%;display: block;margin-bottom: .4rem;cursor: help;pointer-events: auto;}.lot__bet-type {color: tan;}.mybet::before {content: "Ваша ставка: ";color: tan;}/* timers */@keyframes timer {100% {opacity: .6;}}.lot__time {min-width: 6em;display: inline-block;}[data-timer="1"] {color: lightcoral;animation: timer .5s ease-in-out infinite alternate;}/* form */#form {position: relative;background-color: #262b39;box-shadow: .2rem -.2rem .6rem black;z-index: 10;}#form header {height: 5rem;line-height: 5rem;padding: 0 1em;border-top: .1rem solid #545e73;}#form header::after {content: counter(lot);margin-left: .4em;color: tan;}#form__lot {display: flex;background: transparent;border: .1rem solid #4f5058;border-width: .1rem 0;}#form footer {padding: .5em;display: flex;justify-content: space-between;align-items: center;overflow: hidden;}#form.__minimized > :nth-child(n+2) {display: none;}#form__input {width: 6em;padding: .4rem;margin-left: .5rem;color: #ccbeac;background-color: #222;border: .1rem solid #545454;}#form__input:invalid {border-color: tomato;}#form__submit-box {display: flex;align-items: center;}#form__submit {min-width: 14rem;float: right;padding: 1rem;background-color: #3b6369;background-image: linear-gradient(#609b9b, #425f93);border: .1rem solid gray;}#form__submit:hover {filter: saturate(1.4);}#form__submit:active {transform: scale(.9);}#form :disabled {color: #aaa;background: #666;pointer-events: none;}#form__loader {width: 1.6rem;height: 1.6rem;margin-right: 1em;border: .2rem solid #91c8df;border-top-color: transparent;border-radius: 50%;opacity: 0;transition: opacity .3s .2s;animation: spin 1s linear infinite;}.__progress #form__loader {opacity: 1;transition-delay: 0s;}/* notify */#notices {position: absolute;right: 0; bottom: 0;}.notice {font-size: .9em;width: 35rem;min-height: 3rem;line-height: 1.4;position: absolute;right: 1rem; bottom: 6rem;padding: 1rem;text-indent: 2rem;color: #95bcd8;background-color: #2e313d;border: .1rem solid;box-shadow: 0 0 .4rem black;overflow: hidden;white-space: pre-line;opacity: 0;visibility: hidden;transform: translateY(4rem);transition: transform .5s 1s, opacity .5s, visibility .5s;transition-timing-function: ease-in-out;z-index: 10;}.notice:hover,.notice.__shown {opacity: 1;visibility: visible;transform: translateY(0);transition-delay: 0s;}.notice.__success {color: #7cdf9b;}.notice.__warn {color: #e6bc60;}.notice.__error {color: #ea7272;}.notice::before {content: "";width: 1.6rem;height: 1.6rem;position: absolute;left: 1rem; top: 1.2rem;background: url("https://dcdn.heroeswm.ru/i/help/help_ico1.png") center / contain;filter: grayscale(1) brightness(2);}/* art_info */#art_info {font-size: 1.4rem;line-height: 1.3;max-width: 90rem;min-width: 70rem;display: flex;position: absolute;left: 0; top: 0;color: #ddd;background-color: #262a39;background-image: linear-gradient(45deg, #202140, #2d4956);outline: .2rem solid #325e7d;box-shadow: 0 0 .6rem .2rem black;opacity: 0;visibility: hidden;transition-property: top, opacity, visibility;transition-duration: .1s;z-index: 20;}#art_info:hover,#art_info.__shown {opacity: 1;visibility: visible;}#art_info:hover::before,#art_info.__shown::before {content: "";width: 16rem;position: absolute;left: -2rem; top: -6rem; bottom: -6rem;z-index: -1;}.global_container_block_header {position: absolute;right: 2rem; top: 2rem;text-transform: uppercase;filter: saturate(3);}.art_info_left_block {padding: 2rem 1rem 2rem 2rem;}.s_art_prop_amount_icon {min-height: 3rem;display: flex;justify-content: center;align-items: center;margin-top: .2rem;color: #eee;background-color: #3b4b69;background-image: linear-gradient(#5f8d84, #2c4168);border: .1rem solid #78878d;}.s_art_prop_amount_icon:hover {filter: saturate(1.5);}.s_art_prop_amount_icon:active {transform: translate(.1rem, .1rem);}.s_art_prop_amount_icon img {width: 2rem;margin-right: .5rem;}#art_info .cre_mon_image1 {display: none;}.art_info_desc {padding: 2rem;background: transparent !important;}#art_info font {color: inherit;}#art_info td {color: #ddd;}#art_info b {color: #bfb3a2;}#art_info i {color: #9fbec8;}#art_info .rs {margin: 0 .2rem;}#art_info [href*="section=40"] {color: #70b27d;text-decoration: underline;}/* house, obj_share, cert */@font-face {font-family: "Material Icons";font-style: normal;font-weight: 400;font-display: swap;src: url("https://fonts.gstatic.com/s/materialicons/v98/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2") format("woff2");}.m-icon {font-family: "Material Icons", sans-serif;font-size: 2rem;line-height: 1;display: inline-block;text-rendering: optimizeLegibility;-webkit-font-smoothing: antialiased;}[data-cat="dom"] .lot__info {position: relative;}.obj-id {filter: saturate(.5) brightness(1.1);}.place {color: #98bebb;}.house__stars {position: absolute;right: .5rem; top: 1rem;}.house__star {font-size: 1.4rem;color: #e6d78a;}/* loader */#loader {width: 5rem;height: 5rem;position: absolute;left: 0; right: 0; top: 0; bottom: 0;margin: auto;color: skyblue;border-radius: 50%;box-shadow: inset -.2rem -.2rem .2rem currentColor;opacity: 0;visibility: hidden;transition: opacity .3s .1s, visibility .3s .1s;animation: spin 1s linear infinite;z-index: 110;}.__loading #loader {opacity: 1;visibility: visible;transition-delay: 0s;}/* my bets */#mybets-btn.__active {background-color: #344342;}#mybets-btn[data-counter="0"]:not(.__active) {color: gray;background-color: #3e4044;pointer-events: none;}#mybets-btn[data-counter]::after {content: "( " attr(data-counter) " )";margin-left: .4em;color: #aaa;}#lots.mybets .lot {display: flex;}@keyframes processing {0% {content: "";}25% {content: ".";}50% {content: "..";}75% {content: "...";}}.lot__processing {font-family: Consolas, monospace;font-size: 1.2em;display: flex;justify-content: center;align-items: center;position: absolute;left: 0; right: 0; top: 0; bottom: 0;color: #eee;background-color: #333a;z-index: 10;}.lot__loading::after {content: "";width: 0;display: inline-block;animation: processing .5s steps(1) infinite;}/* contextmenu */.contextmenu-is-shown::after {content: "";position: absolute;left: 0; right: 0; top: 0; bottom: 0;z-index: 150;}#contextmenu {font-size: .9em;width: 40rem;position: absolute;left: 0; top: 0;padding: .5rem 0;color: #ccc;background-color: #2f2f2f;border: .1rem solid #555;box-shadow: .2rem .2rem .2rem black;z-index: 200;}#contextmenu:empty {display: none;}.contextmenu__cmd {line-height: 2;padding: 0 1rem;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}.contextmenu__cmd:hover {background-color: #444;}.contextmenu__cmd::before {content: attr(data-key);float: right;margin-left: 1rem;opacity: .7;}/* ============== */[href^="pl_info"] {color: lightblue;}.c-set {color: #78ac78;}.lot a:hover {color: #db8779;}@media screen and (max-width: 1320px) {#aside_2 {width: .2rem;min-width: auto;z-index: 110;}#aside_2:hover,#aside_1:hover + #aside_2 {width: 27rem;min-width: 27rem;}.menu__list {z-index: 140;}}@media screen and (max-width: 960px), screen and (max-height: 600px) {:root {font-size: 9px;}}';
    document.head.append(this);
  });

  const filtersStyle = $.parseNode('<style class="auc_css" id="filters_css"></style>', function() {
    let css = '';
    const filters = settings.filters;

    for (let key in filters) {
      if (filters[key] != null) css += `, [data-params*="${key}=${filters[key] ^ 1}"]`;
    }

    this.textContent = css && `${css.slice(2)} {display: none}`;
    document.head.append(this);
  });

  const targetStyle = $.parseNode('<style class="auc_css" id="target_css"></style>', function() {
    const colors = ['#38424f', '#75c1ed', '#2d2e3063'];

    this.updateCSS = () => {
      let params = getSearchParams(location.search);

      if (!params) return (this.textContent = '');

      let key = params.cat === 'res' ? 'type' : 'art_type';
      let catCss = !params.cat ? '' : `#cat-${params.cat} > h4 {background-color: ${colors[0]};}`;
      let linkCss = !params[key] ? '' : `a[href$="type=${params[key]}"] {color: ${colors[1]}; background-color: ${colors[2]};}`;

      this.textContent = catCss + linkCss;
    };

    this.updateCSS();
    document.head.append(this);
  });

  const plStyle = $.parseNode('<style class="auc_css" id="pl_css"></style>', function() {
    this.paintPlayer = () => {
      this.textContent = `[href="pl_info.php?id=${plid}"], [href="pl_info.php?nick=${settings.playerName}"] {color: #59d4b6;}`;
    };

    settings.playerName && this.paintPlayer();
    document.head.append(this);
  });

  const aucElem = $.parseNode('<main id="auction"></main>', function() {
    const betsLength = Object.keys(betsData).length;
    const filtersSVG = `<svg id="filters-icon" viewBox="0 0 16.5 17" width="18" height="18">
      <path d="M175.051,8.283V.478a.478.478,0,1,0-.955,0v7.8a2.425,2.425,0,0,0,0,4.755v3.474a.478.478,0,1,0,.955,0V13.038a2.425,2.425,0,0,0,0-4.755Zm-.478,3.846a1.468,1.468,0,1,1,1.468-1.468A1.469,1.469,0,0,1,174.574,12.129Z" transform="translate(-166.302 0)"></path>
      <path d="M9.751,4.278V.478a.478.478,0,0,0-.955,0v3.8a2.425,2.425,0,0,0,0,4.755v7.479a.478.478,0,0,0,.955,0V9.029a2.423,2.423,0,0,0,0-4.752ZM9.274,8.123a1.468,1.468,0,1,1,1.468-1.468A1.469,1.469,0,0,1,9.274,8.123Z" transform="translate(-6.85 0)"></path>
      <path d="M339.351,4.278V.478a.478.478,0,0,0-.955,0v3.8a2.425,2.425,0,0,0,0,4.755v7.483a.478.478,0,0,0,.955,0V9.029a2.423,2.423,0,0,0,0-4.752Zm-.478,3.846a1.468,1.468,0,1,1,1.468-1.468A1.469,1.469,0,0,1,338.874,8.123Z" transform="translate(-324.789 0)"></path>
    </svg>`;
    const eyeSVG = '<svg id="artlist-eye" viewBox="0 0 576 512" width="20" height="20"><path d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"></path></svg>';

    const filtersHTML = ((data) => {
      const active = (key, val) => data[key] === val ? ' __active' : '';
      const keys = {
        once: ['Продажа', 'Торги'],
        full: ['Целые', 'Слом'],
        type: ['Сетовые', 'Не сетовые'],
        craft: ['С крафтом', 'Без крафта']
      };

      return Object.keys(keys).map(key => {
        let values = keys[key];

        return `
          <div class="filters__group">
            <p class="filters__item${active(key, 1)}" data-filter="${key}=1">${values.shift()}</p>
            <p class="filters__item${active(key, 0)}" data-filter="${key}=0">${values.shift()}</p>
          </div>`;
      }).join('');
    })(settings.filters);

    const sortsHTML = (() => {
      const {sort, order} = settings;
      const active = (key) => key === sort ? ` data-order="${order}"` : '';
      const keys = {
        name: 'Товар',
        type: 'Ставка',
        cost: 'Цена/шт.',
        time: 'Время',
        owner: 'Владелец',
      };

      return Object.keys(keys).map(key => {
        let text = keys[key];
        let bySort = `by${key[0].toUpperCase() + key.slice(1)}`;

        return `<span class="a-td sorts__item _${key}" data-sort="${bySort}"${active(bySort)}>${text}</span>`;
      }).join('');
    })();

    this.innerHTML = `
      <header id="auction__header">
        <a id="refresh" href="/auction.php">Auction</a>
        <span id="version">${version}</span>
        <a id="author" href="/pl_info.php?id=5781303">Мифист</a>
        <div id="resources"></div>
      </header>
      <div id="auction__container">
        <aside id="aside_1">
          <nav id="hwm-nav"></nav>
        </aside>
        <aside id="aside_2">
          <header id="player">
            <p><a href="/pl_info.php?id=${plid}" id="player__name">${settings.playerName}</a> <a id="player__faction" href="/castle.php?change_faction_dialog=1"></a></p>
            <p><span id="coin" class="coin">$</span><span id="player__gold" class="gold"></span></p>
          </header>
          <nav id="categories" class="ui-scroll"></nav>
          <footer id="new-lot"><a id="new-lot__link" href="/auction_new_lot.php">Выставить лот</a></footer>
        </aside>
        <section id="main">
          <div class="main__top">
            <div class="a-box">
              ${eyeSVG}
              <button id="artlist-btn" class="a-btn">Все артефакты</button>
              <div id="artlist" class="ui-scroll a-list"></div>
            </div>
            <div class="a-box">
              <button id="setlist-btn" class="a-btn">Комплекты</button>
              <div id="setlist" class="ui-scroll a-list"></div>
            </div>
            <div class="a-box" id="search-box">
              <input id="search" class="a-input __left" type="text" placeholder="Найти лот... (Ctrl + /)" spellcheck="false" autocomplete="off" pattern="[а-яА-Яё\\s\\d-]+">
              <div id="search-list" class="ui-scroll a-list"></div>
              <button id="ext-search" class="action${!settings.extSearch ? '' : ' __active'}" title="Поиск в подстроках">*Aa*</button>
              <span id="search-reset" title="[ Esc ]">&times;</span>
            </div>
            <div class="a-box${!chosenList[0] ? ' __empty' : ''}" id="chosen-box">
              <button id="chosen-toggle" class="action">+</button>
              <button id="chosen-btn" class="a-btn __left">Избранное</button>
              <div id="chosen" class="ui-scroll a-list"></div>
              <div id="chosen-input-box">
                <input id="chosen-input" class="a-input __left" type="text" placeholder="Название закладки" spellcheck="false" autocomplete="off">
                <button id="chosen-add" class="action">OK</button>
              </div>
            </div>
          </div>
          <div class="main__top">
            <div id="filters-box" class="a-box">
              <button id="filters-remove" class="action">&times;</button>
              <button id="filters-btn" class="a-btn __left">${filtersSVG}Фильтры</button>
              <div id="filters" class="ui-scroll a-list">${filtersHTML}</div>
              <span id="filters-counter"></span>
            </div>
            <div id="mybets-box" class="a-box">
              <button id="mybets-btn" class="a-btn" data-counter="${betsLength}">Мои ставки</button>
            </div>
          </div>
          <div id="sorts">${sortsHTML}</div>
          <div id="lots-container" class="ui-scroll">
            <section id="lots" data-order=${settings.order}></section>
          </div>
          <section id="form" class="__minimized">
            <header>Лотов показано:</header>
            <div id="form__lot" class="lot"></div>
            <footer>
              <div>
                <span>Кол-во лотов</span>
                <input id="form__input" type="number" autocomplete="off">
              </div>
              <div id="form__submit-box">
                <span id="form__loader"></span>
                <button id="form__submit">Купить лот</button>
              </div>
            </footer>
          </section>
        </section>
      </div>
      <section id="art_info"></section>
      <div id="contextmenu"></div>
      <div id="loader"></div>`;

    document.body && document.body.prepend(this);
  });

  function createMenu(target) {
    const layout = [];
    const dcdn = 'https://dcdn.heroeswm.ru/i/new_top/_panel';
    const menu = {
      Character: [['home', 'Персонаж'], ['inventory', 'Инвентарь'], ['shop', 'Магазин артефактов'], ['auction', 'Рынок'], ['army', 'Набор армии'], ['castle', 'Замок'], ['skillwheel', 'Навыки'], ['sms', 'Личная почта'], ['transfer', 'Передача ресурсов'], [`pl_transfers.php?id=${plid}`, 'Протокол передач']],

      Map: [['map', 'Карта'], ['map.php?st=mn', 'Добыча'], ['map.php?st=fc', 'Обработка'], ['map.php?st=sh', 'Производство'], ['map.php?st=hs', 'Дома']],

      Battles: [['bselect', 'Битвы'], [`pl_warlog.php?id=${plid}`, 'Протокол боев'], ['one_to_one', 'Дуэли'], ['group_wars', 'Групповые бои'], ['pvp_guild', 'Гильдия Тактиков'], ['task_guild', 'Гильдия Стражей'], ['leader_guild', 'Гильдия Лидеров'], ['ranger_list', 'Заявки Рейнджеров'], ['mapwars', 'Бои за территории'], ['tournaments', 'Турниры']],

      Tavern: [['tavern', 'Таверна'], [`pl_warlog.php?id=${plid}`, 'Протокол игр'], ['tavern.php?form=1', 'Создать заявку']],

      Roulette: [['roulette', 'Рулетка'], ['inforoul', 'Прошлая игра'], ['allroul', 'История игр'], ['help.php?section=21', 'Правила игры'], ['gift_box_log', 'Редкие ларцы']],

      Rate: [['plstats', 'Рейтинг воинов'], ['clanstat', 'Рейтинг боевых кланов'], ['plstats_hunters', 'Рейтинг охотников '], ['plstats_merc', 'Рейтинг наемников '], ['sholders_stat', 'Рейтинг акционеров'], [`pl_hunter_stat.php?id=${plid}`, 'Личные достижения']],

      Forum: [['forum', 'Все форумы'], ['forum_thread.php?id=1', 'Официальные объявления'], ['forum_thread.php?id=2', 'Общий игровой'], ['forum_thread.php?id=10', 'Вопросы и помощь в игре'], ['help', 'Об игре']],
    };

    Object.keys(menu).forEach(key => {
      let html = '';
      const entries = menu[key];
      const [href, text] = entries.shift();

      entries.forEach(entry => {
        let [href, text] = entry;

        if (!href.includes('?')) href += '.php';

        html += `<a class="menu__item" href="/${href}">${text}</a>`;
      });

      layout.push(`<div class="menu" id="menu-${key.toLowerCase()}">
        <a class="menu__link" href="/${href}.php"><img class="menu__icon" src="${dcdn + key}.png" alt=""></a>
        <div class="menu__list" data-name="${text}">${html}</div>
      </div>`);
    });

    target.innerHTML = layout.join('');
  }

  function addRedLink(target) {
    if (!target) return;

    let menu = $('#menu-battles .menu__list', aucElem);
    let {pathname: path, textContent: text} = target.closest('a');

    menu.append($.parseNode(`<a class="menu__item __red" href="${path}">${text}</a>`));
  }

  function updateAuction() {
    appendAuc();

    let aucXHR = null;
    let activeLot = null;
    let _params = getSearchParams(location.search) || {};

    const artsData = document.artsData || {};
    const aucClassList = aucElem.classList;
    const allLots = [];
    const allSets = {
      "hunt_set": {
        rus: "Охотника",
        arts: [ "hunter_sword1", "hunter_shield1", "hunter_boots1", "hunter_jacket1", "hunter_bow1", "hunter_gloves1", "hunter_gloves1", "hunter_pendant1", "hunter_hat1" ]
      },
      "mhunt_set": {
        rus: "Мастера-охотника",
        arts: [ "hunterdsword", "huntersword2", "hunterdagger", "huntershield2", "hunter_boots2", "hunter_boots3", "hunter_armor1", "hunter_mask1", "hunter_bow2", "hunter_arrows1", "hunter_amulet1", "hunter_ring1", "hunter_ring2", "hunter_helm", "hunter_roga1" ]
      },
      "ghunt_set": {
        rus: "Великого охотника",
        arts: [ "gm_sword", "gm_kastet", "gm_defence", "gm_spdb", "gm_arm", "gm_protect", "gm_abow", "gm_3arrows", "gm_amul", "gm_sring", "gm_rring", "gm_hat" ]
      },
      "bst_set": {
        rus: "Зверобоя",
        arts: [ "sh_sword", "sh_spear", "sh_shield", "sh_boots", "sh_armor", "sh_cloak", "sh_bow", "sh_4arrows", "sh_amulet2", "sh_ring1", "sh_ring2", "sh_helmet" ]
      },
      "vor": {
        rus: "Вора",
        arts: [ "thief_ml_dagger", "thief_fastboots", "thief_goodarmor", "thief_cape", "thief_arb", "thief_neckl", "ring_of_thief", "ring_of_thief", "thief_msk" ]
      },
      "nal": {
        rus: "Налётчика",
        arts: [ "tm_knife", "tm_boots", "tm_armor", "tm_cape", "tm_arb", "tm_amulet", "tm_wring", "tm_mring", "tm_msk" ]
      },
      "rang": {
        rus: "Рейнджера",
        arts: [ "r_bigsword", "r_magy_staff", "r_dagger", "r_goodscroll", "r_bootsmb", "r_zarmor", "r_clck", "r_bow", "r_warriorsamulet", "r_m_amulet", "r_warring", "r_magicsring", "r_helmb" ]
      },
      "comm": {
        rus: "Тактика",
        arts: [ "tactaz_axe", "tactmag_staff", "tactsm0_dagger", "tactdff_shield", "tactzl4_boots", "tactcv1_armor", "tactpow_cloack", "tact765_bow", "tactms1_mamulet", "tact1w1_wamulet", "tactspw_mring", "tactwww_wring", "tacthapp_helmet" ]
      },
      "rec": {
        rus: "Вербовщика",
        arts: [ "verb11_sword", "vrb_shild", "verbboots", "v_1armor", "ve_helm" ]
      },
      "naemv": {
        rus: "Наёмника-воина",
        arts: [ "merc_sword", "merc_dagger", "merc_boots", "merc_armor" ]
      },
      "mil": {
        rus: "Рыцаря-воина",
        arts: [ "knightsword", "knightshield", "knightboots", "knightarmor", "knighthelmet" ]
      },
      "pal": {
        rus: "Паладина",
        arts: [ "paladin_sword", "paladin_shield", "paladin_boots", "paladin_armor", "paladin_helmet", "paladin_bow" ]
      },
      "necrn": {
        rus: "Некроманта-ученика",
        arts: [ "necr_staff", "necr_robe", "necr_helm", "necr_amulet" ]
      },
      "mags": {
        rus: "Мага-ученика",
        arts: [ "mage_staff", "mage_scroll", "mage_boots", "mage_robe", "mage_cape", "mage_hat" ]
      },
      "velm": {
        rus: "Великого мага",
        arts: [ "gmage_staff", "gmage_scroll", "gmage_boots", "gmage_armor", "gmage_cloack", "gmage_crown" ]
      },
      "elfs": {
        rus: "Эльфа-скаута",
        arts: [ "elfbow", "elfboots", "elfshirt", "elfamulet" ]
      },
      "elfv": {
        rus: "Эльфа-воина",
        arts: [ "welfsword", "welfshield", "welfboots", "welfarmor", "welfbow", "welfhelmet" ]
      },
      "drd": {
        rus: "Друида",
        arts: [ "druid_staff", "druid_boots", "druid_cloack", "druid_armor", "druid_amulet" ]
      },
      "varv": {
        rus: "Варвара-воина",
        arts: [ "barb_club", "barb_shield", "barb_armor", "barb_boots", "barb_helm" ]
      },
      "slugt": {
        rus: "Слуги тьмы",
        arts: [ "darkelfstaff", "darkelfboots", "darkelfcloack", "darkelfciras", "darkelfpendant", "darkelfkaska" ]
      },
      "dems": {
        rus: "Демона-воина",
        arts: [ "dem_axe", "dem_shield", "dem_bootshields", "dem_armor", "dem_amulet", "dem_helmet" ]
      },
      "gnomv": {
        rus: "Гнома-воина",
        arts: [ "gnomehammer", "gnomeshield", "gnomeboots", "gnomearmor", "gnomehelmet" ]
      },
      "gnomm": {
        rus: "Гнома-мастера",
        arts: [ "gnomem_hammer", "gnomem_shield", "gnomem_boots", "gnomem_armor", "gnomem_helmet", "gnomem_amulet" ]
      },
      "trib": {
        rus: "Степного варвара",
        arts: [ "sv_weap", "sv_shield", "sv_boot", "sv_body", "sv_helm", "sv_arb" ]
      },
      "utrib": {
        rus: "Непокорного варвара",
        arts: [ "nv_weap", "nv_shield", "nv_body", "nv_boot", "nv_helm" ]
      },
      "templ": {
        rus: "Рыцаря солнца",
        arts: [ "kn_weap", "kn_shield", "kn_body", "kn_helm" ]
      },
      "inq": {
        rus: "Инквизитора",
        arts: [ "inq_weap", "inq_boot", "inq_body", "inq_cl", "inq_helm" ]
      },
      "amph": {
        rus: "Амфибии",
        arts: [ "amf_weap", "amf_scroll", "amf_boot", "amf_body", "amf_cl", "amf_helm" ]
      },
      "surv": {
        rus: "Сурвилурга",
        arts: [ "surv_sword_surv", "surv_staffik", "surv_sword2sd", "surv_halberdzg", "surv_axes", "surv_wring1my", "surv_mring1fd", "surv_mring2fpg", "surv_wring2o", "surv_crossbowsurv", "surv_mcloacksv", "surv_cloacksrv", "surv_shieldvv", "surv_scrollcd", "surv_daggermd", "surv_bootsurv", "surv_mbootsbb", "surv_armorsu", "surv_marmoroz", "surv_wamuletik", "surv_mamulka", "surv_helmetpi", "surv_mhelmetcv" ]
      },
      "tm_set": {
        rus: "Времён",
        arts: [ "vtmsword3", "vtmsword2", "vtmsword1", "vtmaxe3", "vtmaxe2", "vtmaxe1", "staff_v3", "staff_v2", "staff_v1", "vrdagger3", "vrdagger2", "vrdagger1", "vmring3", "vmring2", "vmring1", "v-ring3", "v-ring2", "v-ring1", "vbolt3", "vbolt2", "vbolt1", "tj-shield3", "tj-shield2", "tj-shield1", "vscroll-3", "vscroll-2", "vscroll-1", "tj_vboots3", "tj_vboots2", "tj_vboots1", "tj_mtuf3", "tj_mtuf2", "tj_mtuf1", "tjarmor3", "tjarmor2", "tjarmor1", "tmarmor3", "tmarmor2", "tmarmor1", "vbow3", "vbow2", "vbow1", "vtjcloak3", "vtjcloak2", "vtjcloak1", "mtcloak3", "mtcloak2", "mtcloak1", "tjam3", "tjam2", "tjam1", "tj_magam3", "tj_magam2", "tj_magam1", "tj_helmet3", "tj_helmet2", "tj_helmet1", "mhelmv3", "mhelmv2", "mhelmv1", "sph3", "sph2", "sph1" ]
      },
      "mir_set": {
        rus: "Мироходца",
        arts: [ "mh_sword3", "mh_sword2", "mh_sword1", "mir_am3", "mir_am2", "mir_am1", "mir_armor3", "mir_armor2", "mir_armor1" ]
      },
      "pir_set": {
        rus: "Пирата",
        arts: [ "p_pistol3", "p_pistol2", "p_pistol1", "p_sword3", "p_sword2", "p_sword1", "p_dag3", "p_dag2", "p_dag1", "piring3", "piring2", "piring1", "pn_ring3", "pn_ring2", "pn_ring1", "p_cloak3", "p_cloak2", "p_cloak1", "p_boots3", "p_boots2", "p_boots1", "pir_armor3", "pir_armor2", "pir_armor1", "p_amulet3", "p_amulet2", "p_amulet1", "piratehat3", "piratehat2", "piratehat1", "p_compas3", "p_compas2", "p_compas1" ]
      },
      "leader_set": {
        rus: "Полководца",
        arts: [ "polk_sword3", "polk_sword2", "polk_sword1", "polkboots3", "polkboots2", "polkboots1", "polk_armor3", "polk_armor2", "polk_armor1", "polk__helm3", "polk__helm2", "polk__helm1", "gring", "gringd" ]
      },
      "undgr_set": {
        rus: "Подземелий",
        arts: [ "dung_axe1", "dung_axe2", "dung_axe3", "dun_sword3", "dun_sword2", "dun_sword1", "dun_dagger3", "dun_dagger2", "dun_dagger1", "dun_bow3", "dun_bow2", "dun_bow1", "dun_ring3", "dun_ring2", "dun_ring1", "dering", "dun_boots3", "dun_boots2", "dun_boots1", "dun_armor3", "dun_armor2", "dun_armor1", "dun_shield3", "dun_shield2", "dun_shield1", "hm1", "hm2", "dun_amul3", "dun_amul2", "dun_amul1", "crystal" ]
      },
      "razb_set": {
        rus: "Разбойника",
        arts: [ "raxe2", "raxe1", "rsword2", "rsword1", "rdagger2", "rdagger1", "rbow2", "rbow1", "rogring2", "rogring1", "ramul2", "ramul1", "rboots2", "rboots1", "rhelm2", "rhelm1", "rarmor2", "rarmor1", "rshield2", "rshield1", "rcloak2", "rcloak1", "sumka" ]
      },
      "ocean_set": {
        rus: "Океана",
        arts: [ "ocean_dgr3", "ocean_dgr2", "ocean_dgr1", "ocean_boots3", "ocean_boots2", "ocean_boots1", "m_armor3", "m_armor2", "m_armor1", "ocean_cl3", "ocean_cl2", "ocean_cl1", "ocean_bw3", "ocean_bw2", "ocean_bw1", "ocean_m_shield3", "ocean_m_shield2", "ocean_m_shield1", "m_amul3", "m_amul2", "m_amul1", "ocean_hlm3", "ocean_hlm2", "ocean_hlm1" ]
      },
      "avan_set": {
        rus: "Авантюриста",
        arts: [ "adv_clk1", "adv_clk2", "adv_saber2", "adv_saber1", "a_dagger2", "a_dagger1", "adv_armor2", "adv_armor1", "adv_longbow2", "adv_longbow1", "adv_hm2", "adv_hm1", "adv_boot2", "adv_boot1", "adv_neck2", "adv_neck1" ]
      },
      "ed_set": {
        rus: "Единства",
        arts: [ "ed_armr3", "ed_armr2", "ed_armr1", "ed_ring3", "ed_ring2", "ed_ring1" ]
      },
      "forest_set": {
        rus: "Леса",
        arts: [ "forest_blade", "forest_helm", "neut_amulet", "les_cl", "forest_bow", "forest_dagger", "forest_boots", "forest_armor" ]
      },
    };
    const allSetArts = Object.values(allSets).map(that => that.arts).flat(1);
    const allSetArtsRus = {};

    const format = (text, ...rest) => text.replaceAll('{}', () => rest.shift());
    const isStuff = ((reg) => (cat) => reg.test(cat))(/^(res|elem|dom|cert|obj)/);
    const findLot = (id) => allLots.find(lot => lot.id === id);
    const importNode = (node) => document.importNode(node, true);
    const parseGold = (value) => parseInt(value.replaceAll(',', ''));
    const goldToString = (num) => num.toLocaleString('en');

    const setSortsPad = ((target, style) => {
      return function() {
        let dif = target.offsetWidth - target.clientWidth;

        style.paddingRight = `${dif / 10}rem`;
      };
    })($('#lots-container'), $('#sorts').style);

    function goTo(url) {
      let urlData = new URL(url);
      let oldSearch = location.search + location.hash;
      let newSearch = urlData.search + urlData.hash;
      let params = getSearchParams(newSearch);

      oldSearch !== newSearch && history.pushState(params, '', newSearch || '/auction.php');
      loadPage(url);
    }

    function ajax({ url, method = 'GET', timer = 6e3, responseType = 'document', body, success, timeout, error }) {
      let xhr = new XMLHttpRequest();

      xhr.open(method, url);
      xhr.timeout = timer;
      xhr.responseType = responseType;
      xhr.send(body);

      return $.extend(xhr, {
        onload() {
          if (this.status === 200) return success(this.response);

          notify.show({
            type: 'error',
            text: `Ошибка ${this.status}: ${this.statusText}\nЗапрашиваемый url: ${url}`
          });
        },
        onerror() {
          error && error();
          console.error(this);
          notify.show({
            type: 'error',
            text: `Ошибка ${this.status}: ${this.statusText}\nЗапрашиваемый url: ${url}`
          });
        },
        ontimeout() {
          timeout && timeout();
          notify.show({
            type: 'warn',
            text: 'Превышено время ожидания!'
          });
        },
      });
    }

    function getHWMElem(url, callback) {
      aucXHR instanceof XMLHttpRequest && aucXHR.abort();
      aucXHR = ajax({
        url,
        success(resp) {
          let cat = _params.cat;
          let i = (!cat || cat === 'my') ? 3 : 2;
          let hwm_elem = importNode($('[cellpadding="4"] > tbody', resp));

          while (i--) hwm_elem.firstElementChild.remove();

          return callback(hwm_elem);
        },
        error() {
          aucClassList.remove('__loading');
        },
        timeout() {
          aucClassList.remove('__loading');
        },
      });

      return aucXHR;
    }

    function loadPage(url = location.href) {
      _params = getSearchParams(location.search) || {};
      aucClassList.add('__loading');
      timers.length && timers.clearAll();
      activeLot && form.minimize(1);

      return getHWMElem(url, (hwm_elem) => {
        let cat = _params.cat;
        let hash = location.hash.slice(4);
        let targetLot;

        bets.shown && bets.hide();
        filters.partial(cat === 'part' || isStuff(cat));
        filters.disable(!cat || cat === 'obj_share');
        targetStyle.updateCSS();
        lotsBox.load(hwm_elem);
        setSortsPad();
        timers.switchTimers();
        targetLot = hash && findLot(hash);
        targetLot && targetLot.target.classList.add('__target');
        aucClassList.remove('__loading');
      });
    }

    function addImage(link) {
      let path = 'https://dcdn.heroeswm.ru/i/artifacts/';
      let key = link.search.split('=').pop();
      let value = artsData[key];
      let name = !value ? '' : value === '&' ? key : value.replace('&', key);
      let img;

      if (!value) return;

      img = new Image(25);
      img.className = 'a-link__img';
      img.src = path + name + '.png';
      link.prepend(img);
    }

    function initialize(callback) {
      resources.__init__();
      player.__init__();
      artsSelect.__init__();
      setArtsSelect.__init__();
      categories.__init__();
      search.__init__();
      chosen.__init__();
      filters.__init__();
      sort.__init__();
      artInfo.__init__();
      form.__init__();
      lotsBox.__init__();
      bets.__init__();
      contextmenu.__init__();
      notify.__init__();
      callback();
    }

    // ========================

    class Lot {
      constructor(data) {
        for (let key in data) {
          this[key] = data[key];
        }
      }
      select() {
        let target = this.target;
        let active = activeLot && activeLot.target;

        if (active) {
          active.classList.remove('__active');

          if (target === active) return !form.minimize(1);
        }

        target.classList.add('__active');
        form.refresh((activeLot = this));
      }
      refresh() {
        let test = true;
        let target = this.target;
        let value = +form.inputValue;
        let timer = this.timer && timers.find(this);
        let sell = () => {
          test = false;
          this.sell();
        };

        if (this.once) {
          this.amount -= value;
          this.amount <= 0 && sell();
          player.refreshGold(this.cost * value);
        } else {
          let bet = this.cost;
          let step = Math.round(bet * 0.01);
          let newbet = bet + (step < 3 ? 3 : step);

          this.myBet = value;
          this.cost = newbet;
          this.lastHero = [player.name, `pl_info.php?id=${plid}`];
          player.refreshGold(value);

          if (this.blitz && value >= this.blitz) sell();
          else target.dataset.params += '&mybet=1';
        }

        target.innerHTML = lotsBox.create(this).innerHTML;

        if (timer) timer.elem = $('.lot__time', target);

        return test;
      }
      sell(selled) {
        let target = this.target;

        if (selled || this.time[1] <= 0) {
          let timeElem = $('.lot__time', target);

          timeElem.textContent = '00:00';
          timeElem.removeAttribute('data-timer');
        }

        this.selled = true;
        target.dataset.params += '&selled=1';
      }
      getHwmForm({success, ...rest}) {
        return ajax({
          url: `/auction.php${this.locate}`,
          success: (resp) => success($(`form[name$="${this.id}"]`, resp)),
          ...rest
        });
      }
      reload() {
        let target = this.target;
        let processingEl = $.parseNode(`<div class="lot__processing">
          <span class="lot__loading">Загрузка</span>
        </div>`);

        target.prepend(processingEl);

        return this.getHwmForm({
          timeout: () => processingEl.remove(),
          success: (hwm_form) => {
            if (!hwm_form) {
              this.sell(1);
              processingEl.innerHTML = '<span>Торги закончены.</span>';
              activeLot === this && form.minimize(1);

              return setTimeout(() => {
                processingEl.remove();
                bets.shown && bets.remove(this.id);
              }, 2e3);
            }

            let hwm_target = hwm_form.closest('tr.wb');
            let lotData = lotsBox.getData(hwm_target, this.cat, this.locate);
            let timer = this.timer && timers.find(this);

            $.extend(this, lotData);
            target.innerHTML = lotsBox.create(lotData).innerHTML;
            activeLot === this && form.refresh(this);

            if (timer) {
              timer.value = this.time[1];
              timer.elem = $('.lot__time', target);
              timer.elem.dataset.timer = 1;
              timer.elem.textContent = timers.parseTime(timer.value);

              if (activeLot === this) form.lotElem.innerHTML = target.innerHTML;
            } else if (this.time[1] < 60) {
              this.timerOn();
              timers.length === 1 && timers.activate();
            }
          }
        });
      }
      incrementBetAmount() {
        $('.lot__bet-amount', this.target).textContent = ++this.betAmount;
      }
      timerOn() {
        this.timer = 1;

        timers.add({
          lot: this,
          elem: $('.lot__time', this.target),
          value: this.time[1]
        });
      }
      timerOff() {
        let ind = timers.findIndex(this);

        if (!~ind) return;

        timers.clear(ind);
        this.time[1] = this.timer = 0;
        this.sell(1);

        if (bets.shown) return setTimeout(bets.remove.bind(bets, this.id), 1e3);
        if (activeLot === this) {
          this.target.classList.remove('__active');
          form.minimize(1);
        }
      }
    }

    const timers = (() => {
      let loop = null;
      const _timers = [];
      const completed = [];

      return {
        activate() {
          clearTimeout(loop);

          if (!_timers.length) return;

          _timers.forEach(timer => {
            let {lot, elem, value} = timer;

            if (!~value) return completed.push(lot);

            lot.time[1] = timer.value--;

            if (!elem.offsetWidth) return;

            let formLot = lot === activeLot && form.$lot;
            let formLotElem = formLot && form.lotElem;
            let formTimerElem = formLotElem && $('.lot__time', formLotElem);

            elem.dataset.timer = 1;
            elem.textContent = this.parseTime(value);

            if (!(formLotElem && formLotElem.offsetWidth && formLot.id === lot.id)) return;

            formTimerElem.dataset.timer = 1;
            formTimerElem.textContent = elem.textContent;
          });

          if (completed.length) {
            completed.forEach(lot => lot.timerOff());
            completed.splice(0);
          }

          loop = setTimeout(this.activate.bind(this), 1e3);
        },
        switchTimers() {
          this.clearAll();
          allLots.forEach(lot => lot.time[1] < 60 && lot.timerOn());
          this.activate();
        },
        add(timer) {
          return _timers.push(timer);
        },
        clear(ind) {
          return _timers.splice(ind, 1);
        },
        clearAll() {
          clearTimeout(loop);
          _timers.splice(0);
        },
        find(lot) {
          return _timers.find(timer => timer.lot === lot);
        },
        findIndex(lot) {
          return _timers.findIndex(timer => timer.lot === lot);
        },
        parseTime(value) {
          let min = ('0' + ~~(value / 60)).slice(-2);
          let sec = ('0' + (value % 60)).slice(-2);

          return `${min}:${sec}`;
        },
        get length() {
          return _timers.length;
        },
      };
    })();

    const player = (() => {
      const hwm_gold = $('#ResourceAmount, #res_gold') || $('img[src*="/gold.png"]').parentNode.nextElementSibling;
      const goldEl = $('#player__gold');

      return {
        __init__() {
          this.fill();

          !this.name && ajax({
            url: `/pl_info.php?id=${plid}`,
            success: (resp) => {
              let link = $('[href^="sms-create"]', resp);
              let name = link && link.getAttribute('href').split('=').pop() || prompt('Введите имя вашего персонажа');

              this.name = name;
              this.fill();
              settings.update('playerName', name);
              plStyle.paintPlayer();
            }
          });

          ajax({
            url: `/home.php`,
            success: (resp) => {
              let src = $('[href="castle.php?change_faction_dialog=1"] img', resp).src;
              let img = $.parseNode(`<img src="${src}" alt="" width="15">`);

              $('#player__faction').append(img);
            }
          });
        },

        id: plid,
        name: settings.playerName,
        gold: parseGold(hwm_gold.textContent),
        refreshGold(num) {
          this.gold -= num;
          goldEl.textContent = goldToString(this.gold);
          resources.refresh('gold', -num);
        },
        fill() {
          if (this.name) $('#player__name').textContent = this.name;

          goldEl.textContent = goldToString(this.gold);
        }
      };
    })();

    const resources = ((target) => {
      const elems = {};

      return {
        __init__() {
          const hwmResPanel = $('#ResourcesPanel, #top_res_table, #panel_resourses');

          if (!hwmResPanel) return;

          const resIcons = $$('img', hwmResPanel);
          const getValue = (el) => (el.nextElementSibling || el.parentNode.nextElementSibling).textContent;
          const create = (icon) => {
            let src = icon.src;
            let key = src.match(/(\w+)\.png/)[1];
            let item = $.parseNode(`<div class="res__item" id="res-${key}" data-value="${getValue(icon)}">
              <img src="${src}" alt="" width="24">
            </div>`);

            return (elems[key] = item);
          };

          resIcons.length === 8 && resIcons.pop();
          target.append(...resIcons.map(create));
        },
        refresh(key, n) {
          if (!elems[key]) return;

          let dataset = elems[key].dataset;
          let value = n + parseGold(dataset.value);

          dataset.value = goldToString(value);
        }
      };
    })($('#resources'));

    const lotsBox = ((target) => {
      function paramsToString(params) {
        let entries = Object.entries(params);
        return entries.map(entry => `${entry[0]}=${entry[1]}`).join('&');
      }

      const timeToSec = {
        'д': v => v * 86400,
        'ч': v => v * 3600,
        'мин': v => v * 60,
        'с': v => v >> 0
      };
      const app = {
        getBet(elem, once) {
          let that = {};
          let first = elem.firstChild;

          if (!once && first.nodeType === 3) {
            let td = $('td:last-child', elem);
            let amount = that.betAmount = first.data >> 0;

            if (td) that.blitz = parseGold(td.textContent);
            if (amount) that.lastHero = this.getHero(elem.nextElementSibling, that);
          }

          return that;
        },
        getCost(elem) {
          let value = $('[id^=au] td:last-child', elem).textContent;
          return parseGold(value);
        },
        getDurability(elem) {
          let match = elem.textContent.match(/\d+\/\d+/)[0];
          let values = match.split('/').map(Number);
          let lastRed = values[0] < values[1] && $('font + font:last-child', elem);

          return values.concat(!!lastRed);
        },
        getHero(elem, that) {
          let link = $('[href^="pl_info"]', elem);
          let name = link && link.textContent;
          let bet = link && link.nextSibling;

          bet = bet && bet.nodeType === 3 && bet.data.slice(2);

          if (that && bet) that.myBet = +bet;

          return !name ? '' : [name, link.getAttribute('href')];
        },
        getMods(elem) {
          let text = elem.textContent;
          let mods = (text.match(/\[[IEAWFDN\d]{2,}\]/) || '_')[0].slice(1, -1);
          let modsEl = mods && $('.art_mods', elem);
          let parts = mods && mods.match(/\w\d/g);
          let colorize = !mods ? null : mod => {
            let colors = {
              "A": "#ab91c7",
              "D": "#a09f9f",
              "E": "#ac6262",
              "F": "#ff8f1b",
              "I": "#d2b48c",
              "N": "#73ac6c",
              "W": "#74b4f6",
            };
            return `<font color="${colors[mod[0]]}">${mod}</font>`;
          };

          return !mods ? null : [mods, parts.map(colorize).join(' '), `<div class="art-mods">${modsEl.innerHTML}</div>`];
        },
        getTime(elem) {
          let sec = 0;
          let value = elem.textContent;
          let parts = value.match(/\d+ (д|ч|мин|с)/g);

          parts && parts.forEach(p => {
            p = p.split(' ');
            sec += timeToSec[p[1]](p[0]);
          });

          return [value, sec];
        },
        getHouse(elem) {
          let link = $('[href^="house_info"]', elem);
          let place = $('b', elem).previousSibling.data.trim();
          let points = ['star_outline', 'star', 'star_half'];
          let hwm_stars = elem.innerHTML.match(/\/star\d+/g).map(x => x.slice(-1)[0]);
          let stars = hwm_stars.map(x => `<span class="house__star m-icon">${points[x]}</span>`).join('');

          return {
            link: link.outerHTML.replace('<a', ' <a class="obj-id"'),
            html: `<p class="place">${place}</p><p class="house__stars">${stars}</p>`
          };
        },
        getShare(elem) {
          let link = $('[href^="object-info"]', elem);
          let place = $('[href^="map.php"]', elem).outerHTML.replace('pi', 'place');
          let details = (elem.textContent.match(/,\s([^[]+)/), RegExp.$1.trim()).replace(/(\d+)/, '$1<br>');

          return {
            link: link.outerHTML.replace('<a', ' <a class="obj-id"'),
            html: `<p class="obj-details">${details}</p><p class="place">${place}</p>`
          };
        },
      };
      const layout = {
        getAttrs(data) {
          let cat = data.cat;
          let isArt = !!data.key;
          let hero = data.lastHero && data.lastHero[0];
          let params = { once: +data.once };
          let [idStr, catStr] = [`data-id="${data.id}"`, ` data-cat="${cat}"`];
          let keyStr = !isArt ? '' : ` data-key="${data.key}"`;
          let playerName = player.name;

          if (isArt && cat !== 'part') {
            params.full = +(data.durability[0] === data.durability[1]);
            params.type = +data.fromSet;
            params.craft = +!!data.mods;
          }

          if (data.owner[0] === playerName) params.mylot = 1;
          if (hero === playerName) params.mybet = 1;

          let paramsStr = cat === 'obj_share' ? ' data-params' : ` data-params="${paramsToString(params)}"`;

          return (idStr + catStr + keyStr + paramsStr);
        },
        getBet(data) {
          if (data.once) return '<span class="lot__bet-type">Купить сразу</span>';
          return `<span class="lot__bet-amount">${data.betAmount}</span>` +
          (!data.blitz ? '' : '<p class="lot__bet-type">Блиц цена:</p>' +
          `<p class="lot__blitz"><span class="gold">${goldToString(data.blitz)}</span><span class="coin">$</span></p>`);
        },
        getAmount(data) {
          let {amount, cat} = data;
          let html = `<span class="lot__amount">${amount}</span>`;
          return (amount > 1 || ['res', 'elements'].includes(cat)) ? html : '';
        },
        getName(data) {
          let {name, cat, fromSet} = data;
          let html = `<p class="lot__name">${name}</p>`;

          if (fromSet) html = html.replace('name', 'name c-set');
          else if (cat !== 'cert' && data[cat]) html = html.replace('</p>', ` ${data[cat].link}</p>`);

          return html;
        },
        getHero(arr) {
          return `<a href="${arr[1]}">${arr[0]}</a>`;
        },
        getDurability(arr) {
          let lastRed = arr[2];
          let equal = arr[0] === arr[1];
          let colorize = equal ? null : (n) => `<font color="lightcoral">${n}</font>`;

          return equal
            ? `${arr[0]}/${arr[1]}`
            : !lastRed
              ? `${colorize(arr[0])}/${arr[1]}`
              : `${colorize(arr[0])}/${colorize(arr[1])}`;
        },
      };

      return {
        __init__() {
          target.addEventListener('click', (e) => {
            let trg = e.target;
            let lotElem = !trg.closest('a') && trg.closest('.lot');
            let lot = lotElem && findLot(lotElem.dataset.id);

            if (!lot) return;

            lot.select();
            setSortsPad();
          });
        },

        target: target,
        getData(elem, cat, locate = location.search) {
          if (cat == null) cat = _params.cat || '';

          let isArt = !isStuff(cat);
          let html = elem.innerHTML;
          let children = elem.children;
          let id = children[4].firstElementChild.name.match(/\d+/)[0];
          let image = $('img:last-of-type', children[0]);
          let imgSrc = image && image.src;
          let link = isArt && $('[href^="art_info"]', children[0]);
          let search = link && link.search;
          let key = search && search.match(/=([^&]+)/)[1];

          if (!cat) {
            if (imgSrc.includes('/parts/')) cat = 'part';
            else if (imgSrc.includes('/obj_share')) cat = 'obj_share';
            else if (imgSrc.includes('/house_cert')) cat = 'cert';
            else if (imgSrc.includes('/auc_dom')) cat = 'dom';
            else if (imgSrc.includes('/r/48/')) cat = 'res';
            else if (imgSrc.includes('/gn_res/')) cat = 'elements';
          }

          let that = {
            id: id,
            cat: cat,
            locate: locate,
            name: cat === 'obj_share' ? 'Акция: объект' : cat === 'cert' ? 'Сертификат 1%' : (elem.textContent.match(/(?:[а-яА-ЯёЁ]+[\s-]?)+/) || ' ')[0].trim(),
            image: imgSrc,
            amount: (html.match(/(\d+)\sшт\./) || ' 1')[1] >> 0,
            once: children[1].childElementCount === 1,
            cost: app.getCost(elem),
            time: app.getTime(children[3]),
            owner: app.getHero(children[4]),
          };

          key && $.extend(that, {
            key: key,
            search: search,
            durability: app.getDurability(children[0]),
            withInfo: html.includes('with_info.png'),
            fromSet: allSetArts.includes(key),
            mods: app.getMods(children[0]),
          });

          if (cat === 'dom') that.dom = app.getHouse(children[0]);
          else if (cat === 'obj_share') that.obj_share = app.getShare(children[0]);
          else if (cat === 'cert') {
            let place = $('b', children[0]).previousSibling.data.trim();
            that.cert = { html: `<p class="place">${place}</p>` };
          }

          return $.extend(that, app.getBet(children[1], that.once));
        },
        create(data) {
          let cat = data.cat;
          let isArt = !!data.key;
          let imgContTag = isArt ? 'a' : 'div';
          let link = !isArt ? '' : ` href="/art_info.php${data.search}"`;
          let html = `
            <div class="lot" ${layout.getAttrs(data)}>
              <div class="a-td _name">
                <${imgContTag} class="lot__box"${link}>
                  <img class="lot__img" src="${data.image}" alt="">
                  ${data.withInfo ? '<span class="with-info">i</span>' : ''}
                  ${layout.getAmount(data)}
                  ${!data.mods ? '' : data.mods[2]}
                </${imgContTag}>
                <div class="lot__info">
                  <a class="lot__id" href="/auction_lot_protocol.php?id=${data.id}">${data.id}</a>
                  ${layout.getName(data)}
                  ${!data[cat] ? '' : data[cat].html}
                  ${!data.mods ? '' : `<p class="mods-scope">${data.mods[1]}</p>`}
                  ${!isArt ? '' : `<p class="lot__durability">${layout.getDurability(data.durability)}</p>`}
                </div>
              </div>
              <div class="a-td _type">${layout.getBet(data)}</div>
              <div class="a-td _cost">
                <p><span class="gold">${goldToString(data.cost)}</span><span class="coin">$</span></p>
                ${!data.lastHero ? '' : layout.getHero(data.lastHero)}
                ${!data.myBet ? '' : '<p class="mybet">' + goldToString(data.myBet) + '</p>'}
              </div>
              <div class="a-td _time"><span class="lot__time">${data.time[0]}</span></div>
              <div class="a-td _owner">${layout.getHero(data.owner)}</div>
            </div>`;

          return $.parseNode(html.trim());
        },
        load(hwm_elem) {
          allLots.splice(0);
          target.innerHTML = '';
          this.fill([...hwm_elem.children]);
          sort[settings.sort]();
          this.appendAll();
        },
        fill(hwm_elems) {
          hwm_elems.forEach(el => {
            let lotData = this.getData(el);
            let lotEl = this.create(lotData);

            lotData.target = lotEl;
            allLots.push(new Lot(lotData));
          });
        },
        appendAll() {
          target.append(...allLots.map(lot => lot.target));
        },
      };
    })($('#lots'));

    const artsSelect = ((target) => {
      return {
        __init__() {
          const hwm_select = $('select[name="ss2"]');
          const hwm_options = [...hwm_select.children].slice(1);
          const selectItem = $.parseNode('<a class="a-link a-list__item"></a>');
          const href = '/auction.php?cat={}&art_type={}';
          const eyeSVG = $('#artlist-eye');

          hwm_options.forEach(option => {
            let item = selectItem.cloneNode();
            let values = option.value.split('#');
            let artName = values[1];

            item.href = format(href, ...values);
            item.textContent = option.textContent;

            if (allSetArts.includes(artName)) {
              item.classList.add('c-set');
              allSetArtsRus[artName] = option.textContent;
            }

            target.appendChild(item);
          });

          eyeSVG.addEventListener('click', (e) => {
            if (eyeSVG.classList.toggle('__switch-on')) this.getArts().forEach(addImage);
            else $$('.a-link__img', target).forEach(img => img.remove());
          });
        },
        getArts() {
          return [...target.children];
        },
        getSetArts() {
          return this.getArts().filter(el => el.classList.contains('c-set'));
        },
        hasImages() {
          return !!$('.a-link__img', target);
        },
      };
    })($('#artlist'));

    const setArtsSelect = ((target) => {
      return {
        __init__() {
          target.addEventListener('click', (e) => {
            let trg = e.target;

            if (trg.classList.contains('setlist__set-name')) {
              let parent = trg.parentNode;

              parent.classList.toggle('__active');

              if (parent.childElementCount === 1) parent.appendChild(this.createList(parent.dataset.set));
            }
          });

          Object.keys(allSets).forEach(this.addContainer);
        },
        addContainer(key) {
          let elem = $.parseNode(`<div class="setlist__set" data-set="${key}"><h4 class="setlist__set-name c-set">${allSets[key].rus}</h4></div>`);

          target.appendChild(elem);
        },
        createList(key) {
          let container = $.parseNode('<div class="setlist__arts"></div>');
          let elems = this.getElems(allSets[key].arts);

          if (!elems.length) return container;

          container.append(...elems.sort((a, b) => {
            a = a.textContent;
            b = b.textContent;

            return a > b ? 1 : a < b ? -1 : 0;
          }));

          return container;
        },
        getElems(keys) {
          let arts = artsSelect.getSetArts();

          return keys.map(key => {
            let rus = allSetArtsRus[key];
            let art = rus && arts.find(art => art.textContent === rus);

            if (art) {
              art = art.cloneNode(true);
              art.classList.remove('c-set');
              addImage(art);
            }

            return art;
          }).filter(Boolean);
        },
      };
    })($('#setlist'));

    const categories = ((target) => {
      const inners = [null];

      return {
        __init__() {
          const hwm_elem = $('.wblight[valign]');
          const hwm_elems = $$('[id^="mark_"]:not([id*="info"])', hwm_elem);
          const hwm_new_lot = $('[href="auction_new_lot.php"]', hwm_elem);
          const my = $('[href="/auction.php?cat=my&sort=0"]', hwm_elem);
          let res = this.getResHTML(hwm_elem.firstElementChild);

          hwm_elems.forEach(el => {
            let id = el.id.slice(5);
            let href = (el.children[1].getAttribute('href') || '#').replace('&sort=0', '');
            let {name, len} = this.matchText(el);
            let script = el.nextElementSibling.nextElementSibling;

            inners.push(script.textContent);
            res += this.catHTML({id, href, name, len});
          });

          if (my) {
            res += this.catHTML({
              id: 'my',
              href: '/auction.php',
              name: 'Ваши товары',
              len: this.matchText(my).len
            });
          }
          if (!hwm_new_lot) $('#new-lot').innerHTML = 'Рынок не построен';

          target.addEventListener('click', (e) => {
            let trg = e.target;

            if (!trg.classList.contains('category__heading')) return;

            let parent = trg.parentNode;
            let menu = trg.nextElementSibling;
            let test = !!menu.childElementCount;
            let id = parent.id.slice(4);

            if (!test) this.createList(menu);

            let height = menu.firstElementChild.offsetHeight;

            if (!parent.classList.toggle('__active')) menu.removeAttribute('style');
            else menu.style.maxHeight = `${menu.childElementCount * height}px`;

            if (test) return;

            if (this.checkCat(id)) this.colorizeArts(menu);
            else if (id === 'elements') this.extElements(menu);
          });

          hwm_elem.remove();
          target.innerHTML = res;
        },
        checkCat(id) {
          let reg = /part|obj_share|cert|dom|medals|elements|res/;
          return !reg.test(id);
        },
        createList(elem) {
          let inner = inners[$.index(elem.parentNode)].match(/&nbsp[^']+/)[0];
          elem.innerHTML = inner.replace(/&nbsp;|<br>|<\/font>|<font[^>]*>|&sort=0/gi, '').replace(/href=/g, 'class="category__item" href=');
        },
        getResHTML(elem) {
          function getInner(elem) {
            let str = '';

            while (elem.tagName === 'A') {
              let href = elem.getAttribute('href');
              let {src, title} = elem.firstElementChild;

              str += `<a class="category__item" href="${href}"><img class="category__img" src="${src}" alt="" width="16">${title}</a>`;
              elem = elem.nextElementSibling;
            }

            return str;
          }

          let len = elem.textContent.match(/\d+/)[0];

          return `
            <div class="category" id="cat-res">
              <h4 class="category__heading"><a href="/auction.php?cat=res" class="category__all">${len}</a> Ресурсы</h4>
              <div class="category__items">
                ${getInner(elem.nextElementSibling.nextElementSibling)}
              </div>
            </div>`;
        },
        extElements(elem) {
          let path = 'https://dcdn.heroeswm.ru/i/gn_res/';

          [...elem.children].forEach(el => {
            let key = el.search.split('=').pop();
            let img = $.parseNode(`<img class="category__img" src="${path + key}.png" alt="" width="16">`);

            el.prepend(img);
          });
        },
        colorizeArts(elem) {
          [...elem.children].forEach(el => {
            let art = el.search.split('=').pop();

            if (allSetArts.includes(art)) el.classList.add('c-set');
          });
        },
        matchText(elem) {
          return elem.textContent.match(/(?<name>[^(]+)\((?<len>\d+)/).groups;
        },
        catHTML({id, href, name, len}) {
          return `
              <div class="category" id="cat-${id}">
                <h4 class="category__heading"><a href="${href}" class="category__all">${len}</a> ${name}</h4>
                <div class="category__items"></div>
              </div>`;
        },
      };
    })($('#categories'));

    const search = ((target) => {
      let selectedElem;
      const listEl = target.nextElementSibling;
      const btnSubstr = $('#ext-search');
      const btnReset = btnSubstr.nextElementSibling;

      return {
        __init__() {
          let timeout, down;
          const arrows = ['ArrowUp', 'ArrowDown'];
          const keyup = () => {
            let val = target.value.toLowerCase().trim();

            btnReset.classList.toggle('__shown', !!val);
            listEl.innerHTML = selectedElem = '';
            val && this.createList(val);
          };

          btnSubstr.addEventListener('click', () => {
            settings.update('extSearch', btnSubstr.classList.toggle('__active'));
            target.value && keyup();
          });

          btnReset.addEventListener('click', () => {
            this.clear();
            target.focus();
          });

          target.addEventListener('keydown', (e) => {
            let key = e.key;

            down = 0;

            if (key === 'Escape') return btnReset.click();
            if (key === 'Enter' && selectedElem) {
              selectedElem.click();
              return btnReset.click();
            }
            if (listEl.childElementCount && arrows.includes(key)) {
              down = 1;
              e.preventDefault();
              this.select(key === 'ArrowDown');
            }
          });

          target.addEventListener('keyup', (e) => {
            if (down) return;

            clearTimeout(timeout);
            timeout = setTimeout(keyup, 250);
          });
        },
        getElemes(val) {
          let test = settings.extSearch;

          return artsSelect.getArts().filter(el => {
            let text = el.textContent.toLowerCase();
            return !test ? text.startsWith(val) : text.includes(val);
          });
        },
        createList(val) {
          let elems = this.getElemes(val);
          let artsWithImg = elems.length && artsSelect.hasImages();

          elems.forEach(el => {
            el = el.cloneNode(true);
            !artsWithImg && addImage(el);
            listEl.appendChild(el);
          });
        },
        select(test) {
          let count = listEl.childElementCount;
          let elems = listEl.children;
          let el = selectedElem || test && elems[0] || elems[count - 1];

          selectedElem = !el.id ? el : test ? (el.nextElementSibling || elems[0]) : (el.previousElementSibling || elems[count - 1]);
          el !== selectedElem && el.removeAttribute('id');
          selectedElem.id = 'select-link';
          target.value = selectedElem.textContent;
          selectedElem.scrollIntoView();
        },
        clear() {
          btnReset.classList.remove('__shown');
          listEl.innerHTML = target.value = selectedElem = '';
        },
      };
    })($('#search'));

    const chosen = ((target) => {
      const list = chosenList;
      const inputElem = $('#chosen-input');
      const btn = $('#chosen-toggle');
      const update = () => {
        localStorage[`newAucChosen_${plid}`] = JSON.stringify(list);
        target.classList.toggle('__empty', !list.length);
      };

      return {
        __init__() {
          target.addEventListener('click', (e) => {
            let trg = e.target;
            let action = trg.dataset.chosenAction || trg.id.slice(7);

            return this[action] && this[action](trg);
          });

          inputElem.addEventListener('keyup', (e) => {
            if (e.key === 'Enter') this.add();
            else if (e.key === 'Escape') this.toggle();
          });

          list.length && this.createList();
        },
        create(name, search) {
          const item = $.parseNode(`<div class="a-list__item chosen__item"><a class="a-link chosen__link" href="/auction.php${search}">${name}</a><span data-chosen-action="remove">&times;</span></div>`);
          const link = item.firstChild;
          const id = link.search.split('=').pop();

          allSetArts.includes(id) && link.classList.add('c-set');
          addImage(link);

          return item;
        },
        toggle() {
          if (btn.classList.toggle('__active')) {
            let link = $(`[href="/auction.php${location.search}"]`, aucElem);

            if (!link) return;

            let text = link.classList.contains('category__all')
             ? link.nextSibling.data
             : link.textContent.match(/[^(]+/)[0];

            inputElem.value = text.trim() || '';
            inputElem.focus();
          }
        },
        add() {
          let name = inputElem.value.trim();
          let search = location.search;

          if (!name || this.checkList(name)) return;

          list.push(`${name}|${search}`);
          $('#chosen').append(this.create(name, search));
          this.toggle();
          update();
        },
        remove(elem) {
          list.splice($.index(elem.parentNode), 1);
          elem.parentNode.remove();
          update();
        },
        checkList(name) {
          return list.some(item => item.split('|')[0] === name);
        },
        createList() {
          let items = list.map(item => this.create(...item.split('|')));

          $('#chosen').append(...items);
          target.classList.remove('__empty');
        }
      };
    })($('#chosen-box'));

    const filters = ((target) => {
      const CSS = {};
      const style = filtersStyle;
      const data = settings.filters;
      const refreshCSS = (test, key, value) => {
        CSS[key] = !test ? '' : `, [data-params*="${key}=${value ^ 1}"]`;
      };

      return {
        __init__() {
          target.addEventListener('click', (e) => {
            let trg = e.target;

            if (trg.id === 'filters-remove') {
              $$('.__active', target).forEach(el => el.classList.remove('__active'));
              return this.clear();
            }
            if (trg.dataset.filter) {
              let param = trg.dataset.filter.split('=');
              let isActive = trg.classList.toggle('__active');
              let sib = trg.parentNode.children[$.index(trg) ^ 1];

              sib.classList.remove('__active');
              this.change(isActive, ...param);
            }
          });

          for (let key in data) refreshCSS(data[key] != null, key, data[key]);
        },
        partial(test) {
          return target.classList.toggle('__partial', test);
        },
        disable(test) {
          return target.classList.toggle('__disabled', test);
        },
        change(test, key, value) {
          data[key] = !test ? null : +value;
          refreshCSS(test, key, value);
          this.update();
        },
        clear() {
          for (let key in CSS) CSS[key] = '';
          for (let key in data) data[key] = null;

          this.update();
        },
        update() {
          style.textContent = this;
          settings.update('filters', data);
          setSortsPad();
        },
        toString() {
          let str = Object.values(CSS).join('');
          return str && `${str.slice(2)} {display: none}`;
        },
      };
    })($('#filters-box'));

    const sort = ((target) => {
      const compare = {
        string: (a, b) => a > b ? 1 : a < b ? -1 : 0,
        number: (a, b) => a - b,
      };

      return {
        __init__() {
          target.addEventListener('click', function(e) {
            let trg = e.target;
            let sortBy = trg.dataset.sort;

            if (!sortBy) return;

            [...this.children].forEach(el => el !== trg && el.removeAttribute('data-order'));

            lotsBox.target.dataset.order = (trg.dataset.order ^= 1);
            settings.update('order', trg.dataset.order);

            if (settings.sort !== sortBy) {
              settings.update('sort', sortBy);
              sort[sortBy]();
              lotsBox.appendAll();
            }
          });
        },
        byName() {
          allLots.sort((a, b) => compare.string(a.name, b.name));
        },
        byType() {
          allLots.sort((a, b) => {
            a = a.once ? 99 : a.betAmount || 0;
            b = b.once ? 99 : b.betAmount || 0;

            return compare.number(a, b);
          });
        },
        byCost() {
          allLots.sort((a, b) => compare.number(a.cost, b.cost));
        },
        byTime() {
          allLots.sort((a, b) => compare.number(a.time[1], b.time[1]));
        },
        byOwner() {
          allLots.sort((a, b) => {
            a = a.owner[0].toLowerCase();
            b = b.owner[0].toLowerCase();

            return compare.string(a, b);
          });
        },
      };
    })($('#sorts'));

    const artInfo = ((target) => {
      const layouts = {};
      let timeout, artName, shown;

      return {
        __init__() {
          const mouseover = (trg) => {
            let imgBox = trg.closest('a.lot__box');
            let lotElem = imgBox && imgBox.closest('.lot');
            let key = lotElem && lotElem.dataset.key;

            if (!key) return shown && this.toggle(0);
            if (layouts[key]) {
              if (artName !== key) {
                artName = key;
                target.innerHTML = layouts[key];
              }

              this.setPos(...this.getPos(imgBox));
              return !shown && this.toggle(1);
            }

            this.load(key, (html) => {
              artName = key;
              target.innerHTML = layouts[key] = html;
              this.setPos(...this.getPos(imgBox));
              this.toggle(1);
            });
          };

          aucElem.addEventListener('mouseover', (e) => {
            clearTimeout(timeout);
            timeout = setTimeout(mouseover, 250, e.target);
          });
        },
        load(key, callback) {
          return ajax({
            url: `/art_info.php?id=${key}`,
            success(resp) {
              let elem = resp.getElementById('set_mobile_max_width');
              return callback(elem.innerHTML);
            }
          });
        },
        getPos(elem) {
          let h = target.offsetHeight;
          let max = window.innerHeight;
          let {top, bottom, right} = elem.getBoundingClientRect();
          let x = ~~right;
          let y = (bottom + h < max) ? ~~bottom : ~~Math.abs(top - h);

          return [x, y];
        },
        setPos(x, y) {
          $.extend(target.style, {
            left: `${x}px`,
            top: `${y}px`,
          });
        },
        toggle(test) {
          shown = !!test;
          target.classList.toggle('__shown', shown);
        },
      };
    })($('#art_info'));

    const notify = ((notices, target) => {
      return {
        __init__() {
          target.addEventListener('transitionend', (e) => {
            let {target: trg, propertyName: name} = e;

            if (name === 'transform' && !trg.__shown) this.remove(trg);
          });

          aucElem.appendChild(target);

          this.show({
            type: 'note',
            text: `Script version: ${version}`
          });
        },
        create({type, text}) {
          if (text.includes('Неверные данные')) text += ' Обновите страницу.';

          let notice = $.parseNode(`<div class="notice __${type}">${text}</div>`);
          let last = notices.slice().pop();

          notice.style.bottom = !last ? '60px' : `${last.offsetHeight + parseInt(last.style.bottom) + 10}px`;
          notices.push(notice);
          notice.__shown = 1;

          return notice;
        },
        show(data) {
          let notice = this.create(data);

          console.log(data.text);
          target.append(notice);
          setTimeout(() => notice.classList.add('__shown'), 60);
          setTimeout(() => {
            notice.__shown = 0;
            notice.classList.remove('__shown');
          }, 4e3);
        },
        remove(notice) {
          notices.splice(notices.indexOf(notice), 1);
          notice.remove();
        }
      };
    })([], $.parseNode('<div id="notices"></div>'));

    const form = ((target) => {
      const lotElem = $('#form__lot');
      const input = $('#form__input');
      const submitBtn = $('#form__submit');
      let $lot;

      return {
        __init__() {
          function inputFn(e) {
            let [val, min, max] = [+input.value, +input.min, +input.max];

            if (val > max) input.value = max;
            if (e.type === 'wheel' && val < min) input.value = min;
            else if (val < 0) input.value = 0;

            if (input.reportValidity && !input.checkValidity()) input.reportValidity();
          }

          input.addEventListener('input', inputFn);

          input.addEventListener('wheel', (e) => {
            let step = (e.deltaY > 0 ? -1 : 1) * (e.shiftKey ? 10 : e.ctrlKey ? 100 : e.altKey ? 1e3 : 1);

            e.preventDefault();
            input.value = step + ~~input.value;
            inputFn(e);
          });

          input.addEventListener('keyup', (e) => e.key === 'Enter' && submitBtn.click());

          submitBtn.addEventListener('click', (e) => {
            if (!input.checkValidity()) {
              return notify.show({
                type: 'error',
                text: 'Некорректное значение ввода!'
              });
            }

            let lot = findLot(lotElem.dataset.id);

            if (!lot) return;

            this.disabled(1);

            try { this.submit(lot); }
            catch(err) {
              e.stopPropagation();
              console.error(err);
            }
          });
        },

        lotElem: lotElem,
        minimize(test) {
          if (test && activeLot) {
            activeLot.target.classList.remove('__active');
            activeLot = null;
          }

          return target.classList.toggle('__minimized', !!test);
        },
        disabled(test) {
          aucClassList.toggle('__progress', !!test);
          submitBtn.disabled = !!test;
        },
        refresh(lot) {
          if (this.minimize(lot.selled)) return;

          let {once, target, cost} = lot;
          let prevEl = input.previousElementSibling;
          let getMin = once ? null : () => {
            let {cat, name} = lot;

            if (cat === 'res') {
              let initial = ['Древесина', 'Руда'].includes(name) ? 180 : 360;

              return initial - initial * 0.20;
            }

            return !lot.betAmount ? cost : this.getMinBet(lot.myBet || cost);
          };
          let getMax = once ? null : () => {
            let {cat, name, blitz} = lot;

            if (cat === 'res') {
              let initial = ['Древесина', 'Руда'].includes(name) ? 180 : 360;

              return initial + initial * 0.20;
            }

            return blitz || Infinity;
          };

          $lot = lot;
          lotElem.innerHTML = target.innerHTML;
          $.extend(lotElem.dataset, target.dataset);
          submitBtn.textContent = once ? 'Купить лот' : 'Сделать ставку';
          submitBtn.disabled = input.disabled = player.gold < cost;
          prevEl.textContent = input.placeholder = once ? 'Кол-во' : 'Ставка';
          input.value = input.min = once ? 1 : getMin();
          input.max = once ? lot.amount : getMax();
        },
        submit(lot) {
          const submit = (hwm_form) => {
            let hwm_link = $('a[onclick]', hwm_form);

            if (lot.once) hwm_link && hwm_link.click();
            else this.evalScript(hwm_link.nextElementSibling);

            let hwm_input = $('input[type="text"]', hwm_form);
            let hwm_btn = $('input[type="submit"]', hwm_form);

            hwm_input.value = input.value;

            if (lot.once) {
              hwm_btn.dispatchEvent(new Event('mousedown'));
              hwm_btn.dispatchEvent(new Event('mouseup'));
            }

            this.send(hwm_form, (notice) => this.result(lot, notice));
          };

          if (hwmForm.name.endsWith(lot.id)) return submit(hwmForm.form);

          return lot.getHwmForm({
            timeout: () => this.disabled(0),
            success: (hwm_form) => {
              if (hwm_form) return submit(hwmForm.replace(importNode(hwm_form)));

              this.disabled(0);

              notify.show({
                type: 'error',
                text: 'Форма, которую вы пытаетесь отправить, не существует.'
              });
            },
          });
        },
        send(hwm_form, callback) {
          return ajax({
            url: hwm_form.action,
            method: 'POST',
            body: new FormData(hwm_form),
            success(resp) {
              let hwm_elem = $('.wbwhite center', resp);
              let text = hwm_elem.textContent;
              let parts = ['null', 'Куплен', 'Вы лидер', 'ные данные', 'слишком мала', 'Минимальная ставка', 'закончены', 'Вы не можете'];
              let types = ['null', 'success', 'success', 'error', 'error', 'error', 'error', 'error'];
              let ind = parts.findIndex(part => text.includes(part));
              let type = types[~ind && ind];

              callback({type, text});
            }
          });
        },
        result(lot, notice) {
          let {type, text} = notice;
          let incrementIsNeeded = !lot.once && !/ные данные|Минимальная ставка|закончены/.test(text);

          this.disabled(0);
          notify.show(notice);
          incrementIsNeeded && lot.incrementBetAmount();

          if (type === 'success') {
            if (lot.cat === 'res') {
              let key = lot.image.match(/(\w+)\.png/)[1];

              resources.refresh(key, +input.value);
            }

            if (lot.refresh()) this.refresh(lot);
            else this.minimize(lot.selled);

            if (!lot.once) {
              lot.betAmount > 1 && this.updateCostFromProtocol(lot);
              bets.add(lot);
            }
          }
          else if (text.includes('слишком мала')) this.updateCost(lot, this.getMinBet(+input.value));
          else if (text.includes('Минимальная ставка')) this.updateCost(lot, text.match(/\d+$/)[0]);
        },
        updateCost(lot, bet) {
          bet >>= 0;
          lot.cost = bet;
          $('._cost .gold', lot.target).textContent = goldToString(bet);
          this.refresh(lot);
        },
        updateCostFromProtocol(lot) {
          ajax({
            url: `/auction_lot_protocol.php?id=${lot.id}`,
            success: (resp) => {
              let last = $('.wbwhite a.pi:first-of-type + b', resp);
              let bet = last && +last.textContent;

              return bet && this.updateCost(lot, bet);
            }
          });
        },
        getMinBet(bet) {
          let step = Math.round(bet * 0.01);
          return bet + (step < 3 ? 3 : step);
        },
        evalScript(script) {
          let text = script.textContent.match(/\{[^}]+/)[0].slice(1);
          new Function(text)();
        },
        get inputValue() {
          return input.value;
        },
        get $lot() {
          return $lot;
        },
      };
    })($('#form'));

    const bets = ((target) => {
      let loaded;
      let shown = 0;
      const allBets = [];
      const btn = $('#mybets-btn');
      const settingsKey = `newAucBets_${plid}`;
      const update = () => {
        btn.dataset.counter = Object.keys(betsData).length;
        localStorage[settingsKey] = JSON.stringify(betsData);
      };

      return {
        __init__() {
          btn.addEventListener('click', () => {
            if (!loaded) return this.load(Object.keys(betsData));

            if (!(shown ^= 1)) {
              this.hide();
              return goTo(location.href);
            }

            const lotsWithTimer = allLots.filter(lot => lot.timer && !lot.once && this.has(lot.id));


            lotsWithTimer.forEach(lot => {
              let bet = allBets.find(that => that.id === lot.id);

              if (bet) bet.time[1] = lot.time[1];
            });

            btn.classList.add('__active');
            aucClassList.add('__loading');
            activeLot && form.minimize(1);
            this.step1();
            this.step2();
            filters.disable(1);
            target.classList.add('mybets');
            aucClassList.remove('__loading');
          });
        },
        load(keys) {
          if (!keys.length) {
            return notify.show({
              type: 'note',
              text: 'Зарегистрированных ставок не найдено.'
            });
          }

          loaded = shown = 1;
          btn.classList.add('__active');
          aucClassList.add('__loading');
          activeLot && form.minimize(1);
          this.step1();

          allBets.forEach(lot => {
            let j = keys.indexOf(lot.id);

            ~j && keys.splice(j, 1);
          });

          const completed = [];
          let len = keys.length;
          let callback = () => {
            this.step2();
            filters.disable(1);
            target.classList.add('mybets');
            aucClassList.remove('__loading');
          };

          if (!len) return callback();

          return keys.forEach(id => {
            let locate = betsData[id];

            return ajax({
              url: `/auction.php${locate}`,
              success: (resp) => {
                let hwm_form = $(`form[name$="${id}"]`, resp);

                if (!hwm_form) completed.push(id);
                else {
                  let cat = resp.URL.match(/cat=(\w+)/);
                  let hwm_target = hwm_form.closest('tr.wb');
                  let lotData = lotsBox.getData(hwm_target, cat && cat[1], locate);
                  let lotEl = lotsBox.create(lotData);

                  lotData.target = lotEl;
                  allBets.push(new Lot(lotData));
                }

                if (--len) return;

                completed.forEach(id => delete betsData[id]);
                update();
                callback();
              }
            });
          });
        },
        step1() {
          timers.length && timers.clearAll();
          allLots.splice(0);
        },
        step2() {
          allLots.push(...allBets);
          target.innerHTML = '';
          sort[settings.sort]();
          lotsBox.appendAll();
          timers.switchTimers();
          setSortsPad();
        },
        has(id) {
          return id in betsData;
        },
        add(lot) {
          if (this.has(lot.id)) return;

          betsData[lot.id] = lot.locate;
          allBets.push(lot);
          update();
        },
        remove(id) {
          if (!this.has(id)) return;

          let lot = findLot(id);

          if (shown) {
            activeLot === lot && form.minimize(1);
            allLots.splice(allLots.indexOf(lot), 1);
            lot.target.remove();
          }

          allBets.splice(allBets.indexOf(lot), 1);
          delete betsData[id];
          update();
        },
        hide() {
          shown = 0;
          btn.classList.remove('__active');
          target.classList.remove('mybets');
        },
        get shown() {
          return shown;
        },
      };
    })(lotsBox.target);

    const contextmenu = ((target) => {
      let shown, lotElem;
      const cmd = (name, text, key) => {
        if (!name) return '';
        return `<p class="contextmenu__cmd" data-action="${name}" data-key="${key}">${text}</p>`;
      };
      const commands = [
        ['auction', 'Купить лот', 'ЛКМ'],
        ['console', 'Показать в консоли', 'Alt + L'],
        ['goto', 'Перейти на страницу лота', ''],
        ['reload', 'Обновить лот', 'Alt + R'],
        ['updAll', 'Обновить все', ''],
        ['addBet', '"Мои ставки": добавить', ''],
      ];

      return {
        __init__() {
          const hide = (el) => shown && !el.closest(`#${target.id}`) && this.hide();

          document.addEventListener('wheel', (e) => hide(e.target));
          document.addEventListener('mousedown', (e) => hide(e.target));
          target.addEventListener('contextmenu', (e) => e.preventDefault());

          target.addEventListener('click', (e) => {
            const trg = e.target;
            const action = trg.dataset.action;
            const lot = lotElem && findLot(lotElem.dataset.id);

            if (!lot || trg === target) return;

            switch (action) {
              case 'auction':
                lot.select();
                setSortsPad();
                break;
              case 'reload':
                lot.reload();
                break;
              case 'console':
                console.log(lot);
                break;
              case 'addBet':
                bets.add(lot);
                break;
              case 'removeBet':
                bets.remove(lot.id);
                break;
              case 'goto':
                goTo(`${location.href.split('?')[0]}${lot.locate || ''}#lot${lot.id}`);
                break;
              case 'updAll':
                allLots.forEach(lot => lot.reload());
                break;
            }

            this.hide();
          });

          lotsBox.target.addEventListener('contextmenu', (e) => {
            e.preventDefault();
            lotElem = e.target.closest('.lot');

            const lot = lotElem && findLot(lotElem.dataset.id);

            lot && this.show(e, lot);
          });
        },
        move(x, y) {
          $.extend(target.style, {
            left: `${x}px`,
            top: `${y}px`,
          });
        },
        hide() {
          shown = 0;
          target.innerHTML = '';
          aucClassList.remove('contextmenu-is-shown');
        },
        show(e, lot) {
          shown = 1;
          target.innerHTML = this.getContent(lot);
          aucClassList.add('contextmenu-is-shown');

          let {clientX: x, clientY: y} = e;
          const {offsetWidth: w, offsetHeight: h} = target;

          if (x > window.innerWidth - w) x = window.innerWidth - w - 2;
          if (y > window.innerHeight - h) y = window.innerHeight - h - 2;

          this.move(x, y);
        },
        getContent(lot) {
          const once = lot.once;
          const exist = !once && bets.has(lot.id);
          const shown = bets.shown;

          commands[0][1] = once ? 'Купить лот' : 'Сделать ставку';
          commands[2][0] = shown ? 'goto' : null;
          commands[4][0] = shown ? 'updAll' : null;
          commands[5][0] = once ? null : !exist ? 'addBet' : 'removeBet';
          commands[5][1] = once ? null : !exist ? '"Мои ставки": добавить' : shown ? 'Удалить' : '"Мои ставки": удалить';

          return commands.map(arr => cmd(...arr)).join('');
        },
        get shown() {
          return shown;
        }
      };
    })($('#contextmenu'));

    const hwmForm = ((target) => {
      return {
        __init__() {
          aucElem.before(target);
        },
        replace(newForm) {
          this.form.replaceWith(newForm);
          return newForm;
        },
        get form() {
          return target.firstElementChild;
        },
        get name() {
          return this.form.name;
        }
      };
    })($.parseNode('<div id="hwm_form-container" hidden><form></form></div>'));

    // ========================

    addRedLink($('.subnav blink, .sh_dd_container_red'));

    document.addEventListener('keydown', (e) => {
      const {code, altKey} = e;

      if ((altKey || code === 'Escape') && contextmenu.shown) return contextmenu.hide();
      if (e.ctrlKey && code === 'Slash') return $('#search').focus();
      if (altKey && code === 'KeyL') {
        let lot = allLots.find(lot => lot === activeLot);
        return lot && console.log(lot);
      }
      if (altKey && code === 'KeyR') {
        let lot = allLots.find(lot => lot === activeLot);
        return lot && lot.reload();
      }
    });

    aucElem.addEventListener('click', (e) => {
      let trg = e.target;
      let link = trg.closest('a');

      if (!e.ctrlKey && link && link.pathname === '/auction.php') {
        e.preventDefault();
        goTo(link.href);
      }
    });

    initialize(() => {
      $$('body > :not(#auction)').forEach(e => e.remove());
      $$('link[rel="stylesheet"], style:not(.auc_css)').forEach(e => e.remove());

      hwmForm.__init__();

      ajax({
        url: '/auction.php?sbn=1&sau=1&snew=0',
        success: () => loadPage()
      });

      let timeout;
      const popstate = () => {
        clearTimeout(timeout);
        timeout = setTimeout(loadPage, 200);
      };

      setTimeout(() => window.addEventListener('popstate', popstate), 500);
    });
  }

  createMenu($('#hwm-nav', aucElem));
  window.addEventListener('load', updateAuction);
  document.addEventListener('DOMContentLoaded', appendAuc);
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址