Tamozhnya1Lib

Библиотека с общими функциями. (Устанавливать не надо)

This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greatest.deepsurf.us/scripts/490927/1360667/Tamozhnya1Lib.js

  1. // ==UserScript==
  2. // @name Tamozhnya1Lib
  3. // @namespace Tamozhnya1
  4. // @author Tamozhnya1
  5. // @description Библиотека с общими функциями. (Устанавливать не надо)
  6. // @version 1.7
  7. // @include *heroeswm.ru/*
  8. // @include *lordswm.com/*
  9. // @grant GM_deleteValue
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_listValues
  13. // @grant GM.xmlHttpRequest
  14. // @grant GM.notification
  15. // @license MIT
  16. // ==/UserScript==
  17.  
  18. const playerIdMatch = document.cookie.match(/pl_id=(\d+)/);
  19. const PlayerId = playerIdMatch ? playerIdMatch[1] : "";
  20. const lang = document.documentElement.lang || (location.hostname == "www.lordswm.com" ? "en" : "ru");
  21. const isEn = lang == "en";
  22. const win = window.wrappedJSObject || unsafeWindow;
  23. const isHeartOnPage = (document.querySelector("canvas#heart") || document.querySelector("div#heart_js_mobile")) ? true : false;
  24. const isMooving = location.pathname == '/map.php' && !document.getElementById("map_right_block");
  25. const isNewInterface = document.querySelector("div#hwm_header") ? true : false;
  26. const isMobileInterface = document.querySelector("div#btnMenuGlobal") ? true : false;
  27. const isMobileDevice = mobileCheck(); // Там нет мышки
  28. const isNewPersonPage = document.querySelector("div#hwm_no_zoom") ? true : false;
  29.  
  30. fetch.get = (url) => fetch({ url });
  31. fetch.post = (url, data) => fetch({ url, method: 'POST', body: data });
  32.  
  33. // Array and object
  34. function groupBy(list, keyFieldOrSelector) { return list.reduce(function(t, item) { const keyValue = typeof keyFieldOrSelector === 'function' ? keyFieldOrSelector(item) : item[keyFieldOrSelector]; (t[keyValue] = t[keyValue] || []).push(item); return t; }, {}); };
  35. function getKeyByValue(object, value) { return Object.keys(object).find(key => object[key] === value); }
  36. function findKey(obj, selector) { return Object.keys(obj).find(selector); }
  37. function pushNew(array, newValue) { if(array.indexOf(newValue) == -1) { array.push(newValue); } }
  38. function sortBy(field, reverse, evaluator) {
  39. const key = evaluator ? function(x) { return evaluator(x[field]); } : function(x) { return x[field]; };
  40. return function(a, b) { return a = key(a), b = key(b), (reverse ? -1 : 1) * ((a > b) - (b > a)); }
  41. }
  42. // HttpRequests
  43. function getRequest(url, overrideMimeType = "text/html; charset=windows-1251") {
  44. return new Promise((resolve, reject) => {
  45. GM.xmlHttpRequest({ method: "GET", url: url, overrideMimeType: overrideMimeType,
  46. onload: function(response) { resolve((new DOMParser).parseFromString(response.responseText, "text/html")); },
  47. onerror: function(error) { reject(error); }
  48. });
  49. });
  50. }
  51. function getRequestText(url, overrideMimeType = "text/html; charset=windows-1251") {
  52. return new Promise((resolve, reject) => {
  53. GM.xmlHttpRequest({ method: "GET", url: url, overrideMimeType: overrideMimeType,
  54. onload: function(response) { resolve(response.responseText); },
  55. onerror: function(error) { reject(error); }
  56. });
  57. });
  58. }
  59. function postRequest(url, data) {
  60. return new Promise((resolve, reject) => {
  61. GM.xmlHttpRequest({ method: "POST", url: url, headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: data,
  62. onload: function(response) { resolve(response); },
  63. onerror: function(error) { reject(error); }
  64. });
  65. });
  66. }
  67. function fetch({ url, method = 'GET', type = 'document', body = null }) {
  68. return new Promise((resolve, reject) => {
  69. const xhr = new XMLHttpRequest();
  70. xhr.open(method, url);
  71. xhr.responseType = type;
  72.  
  73. xhr.onload = () => {
  74. if (xhr.status === 200) return resolve(xhr.response);
  75. throwError(`Error with status ${xhr.status}`);
  76. };
  77.  
  78. xhr.onerror = () => throwError(`HTTP error with status ${xhr.status}`);
  79.  
  80. xhr.send(body);
  81.  
  82. function throwError(msg) {
  83. const err = new Error(msg);
  84. err.status = xhr.status;
  85. reject(err);
  86. }
  87. });
  88. }
  89. // Storage
  90. function getValue(key, defaultValue) { return GM_getValue(key, defaultValue); };
  91. function setValue(key, value) { GM_setValue(key, value); };
  92. function deleteValue(key) { return GM_deleteValue(key); };
  93. function getPlayerValue(key, defaultValue) { return getValue(`${key}${PlayerId}`, defaultValue); };
  94. function setPlayerValue(key, value) { setValue(`${key}${PlayerId}`, value); };
  95. function deletePlayerValue(key) { return deleteValue(`${key}${PlayerId}`); };
  96. function getPlayerBool(valueName, defaultValue = false) { return getBool(valueName + PlayerId, defaultValue); }
  97. function getBool(valueName, defaultValue = false) {
  98. const value = getValue(valueName);
  99. //console.log(`valueName: ${valueName}, value: ${value}, ${typeof(value)}`)
  100. if(value != undefined) {
  101. if(typeof(value) == "string") {
  102. return value == "true";
  103. }
  104. if(typeof(value) == "boolean") {
  105. return value;
  106. }
  107. }
  108. return defaultValue;
  109. }
  110. function setOrDeleteNumberValue(key, value) {
  111. if(!value || value == "" || isNaN(Number(value))) {
  112. deleteValue(key);
  113. } else {
  114. setValue(key, value);
  115. }
  116. }
  117. function setOrDeleteNumberPlayerValue(key, value) { setOrDeleteNumberValue(key + PlayerId, value); }
  118. function getStorageKeys(filter) { return listValues().filter(filter); }
  119. // Html DOM
  120. function addElement(type, data = {}, parent = undefined, insertPosition = "beforeend") {
  121. const el = document.createElement(type);
  122. for(const key in data) {
  123. if(key == "innerText" || key == "innerHTML") {
  124. el[key] = data[key];
  125. } else {
  126. el.setAttribute(key, data[key]);
  127. }
  128. }
  129. if(parent) {
  130. if(parent.insertAdjacentElement) {
  131. parent.insertAdjacentElement(insertPosition, el);
  132. } else if(parent.parentNode) {
  133. switch(insertPosition) {
  134. case "beforebegin":
  135. parent.parentNode.insertBefore(el, parent);
  136. break;
  137. case "afterend":
  138. parent.parentNode.insertBefore(el, parent.nextSibling);
  139. break;
  140. }
  141. }
  142. }
  143. return el;
  144. }
  145. function addStyle(css) { addElement("style", { type: "text/css", innerHTML: css }, document.head); }
  146. function getParent(element, parentType, number = 1) {
  147. if(!element) {
  148. return;
  149. }
  150. let result = element;
  151. let foundNumber = 0;
  152. while(result = result.parentNode) {
  153. if(result.nodeName.toLowerCase() == parentType.toLowerCase()) {
  154. foundNumber++;
  155. if(foundNumber == number) {
  156. return result;
  157. }
  158. }
  159. }
  160. }
  161. function getNearestAncestorSibling(node) {
  162. let parentNode = node;
  163. while((parentNode = parentNode.parentNode)) {
  164. if(parentNode.nextSibling) {
  165. return parentNode.nextSibling;
  166. }
  167. }
  168. }
  169. function getNearestAncestorElementSibling(node) {
  170. let parentNode = node;
  171. while((parentNode = parentNode.parentNode)) {
  172. if(parentNode.nextElementSibling) {
  173. return parentNode.nextElementSibling;
  174. }
  175. }
  176. }
  177. function nextSequential(node) { return node.firstChild || node.nextSibling || getNearestAncestorSibling(node); }
  178. function nextSequentialElement(element) { return element.firstElementChild || element.nextElementSibling || getNearestAncestorElementSibling(element); }
  179. function getSequentialsUntil(firstElement, lastElementTagName) {
  180. let currentElement = firstElement;
  181. const resultElements = [currentElement];
  182. while((currentElement = nextSequential(currentElement)) && currentElement.nodeName.toLowerCase() != lastElementTagName.toLowerCase()) {
  183. resultElements.push(currentElement);
  184. }
  185. if(currentElement) {
  186. resultElements.push(currentElement);
  187. }
  188. return resultElements;
  189. }
  190. function findChildrenTextContainsValue(selector, value) { return Array.from(document.querySelectorAll(selector)).reduce((t, x) => { const match = Array.from(x.childNodes).filter(y => y.nodeName == "#text" && y.textContent.includes(value)); return [...t, ...match]; }, []); }
  191. // Popup panel
  192. function createPupupPanel(panelName, panelTitle, fieldsMap, panelToggleHandler) {
  193. const backgroundPopupPanel = addElement("div", { id: panelName, style: "position: fixed; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgb(0,0,0); background-color: rgba(0,0,0,0.4); z-index: 200;" }, document.body);
  194. backgroundPopupPanel.addEventListener("click", function(e) { if(e.target == this) { hidePupupPanel(panelName, panelToggleHandler); }});
  195. const topStyle = isMobileDevice ? "" : "top: 50%; transform: translateY(-50%);";
  196. const contentDiv = addElement("div", { style: `${topStyle} padding: 5px; display: flex; flex-wrap: wrap; position: relative; margin: auto; padding: 0; width: fit-content; background-image: linear-gradient(to right, #eea2a2 0%, #bbc1bf 19%, #57c6e1 42%, #b49fda 79%, #7ac5d8 100%); border: 1mm ridge rgb(211, 220, 50);` }, backgroundPopupPanel);
  197. if(panelTitle) {
  198. addElement("b", { innerHTML: panelTitle, style: "text-align: center; margin: auto; width: 90%; display: block;" }, contentDiv);
  199. }
  200. const divClose = addElement("span", { id: panelName + "close", title: isEn ? "Close" : "Закрыть", innerHTML: "×", style: "cursor: pointer; font-size: 20px; font-weight: bold;" }, contentDiv);
  201. divClose.addEventListener("click", function() { hidePupupPanel(panelName, panelToggleHandler); });
  202.  
  203. addElement("div", { style: "flex-basis: 100%; height: 0;"}, contentDiv);
  204.  
  205. if(fieldsMap) {
  206. let contentTable = addElement("table", { style: "flex-basis: 100%; width: min-content;"}, contentDiv);
  207. for(const rowData of fieldsMap) {
  208. if(rowData.length == 0) { // Спомощью передачи пустой стороки-массива, указываем, что надо начать новую таблицу после брейка
  209. addElement("div", { style: "flex-basis: 100%; height: 0;"}, contentDiv);
  210. contentTable = addElement("table", undefined, contentDiv);
  211. continue;
  212. }
  213. const row = addElement("tr", undefined, contentTable);
  214. for(const cellData of rowData) {
  215. const cell = addElement("td", undefined, row);
  216. if(cellData) {
  217. if(typeof(cellData) == "string") {
  218. cell.innerText = cellData;
  219. } else {
  220. cell.appendChild(cellData);
  221. }
  222. }
  223. }
  224. }
  225. }
  226. if(panelToggleHandler) {
  227. panelToggleHandler(true);
  228. }
  229. return contentDiv;
  230. }
  231. function showPupupPanel(panelName, panelToggleHandler) {
  232. const backgroundPopupPanel = document.getElementById(panelName);
  233. if(backgroundPopupPanel) {
  234. backgroundPopupPanel.style.display = '';
  235. if(panelToggleHandler) {
  236. panelToggleHandler(true);
  237. }
  238. return true;
  239. }
  240. return false;
  241. }
  242. function hidePupupPanel(panelName, panelToggleHandler) {
  243. const backgroundPopupPanel = document.getElementById(panelName);
  244. backgroundPopupPanel.style.display = 'none';
  245. if(panelToggleHandler) {
  246. panelToggleHandler(false);
  247. }
  248. }
  249. // Script autor and url
  250. function getScriptLastAuthor() {
  251. let authors = GM_info.script.author;
  252. if(!authors) {
  253. const authorsMatch = GM_info.scriptMetaStr.match(/@author(.+)\n/);
  254. authors = authorsMatch ? authorsMatch[1] : "";
  255. }
  256. const authorsArr = authors.split(",").map(x => x.trim()).filter(x => x);
  257. return authorsArr[authorsArr.length - 1];
  258. }
  259. function getDownloadUrl() {
  260. let result = GM_info.script.downloadURL;
  261. if(!result) {
  262. const downloadURLMatch = GM_info.scriptMetaStr.match(/@downloadURL(.+)\n/);
  263. result = downloadURLMatch ? downloadURLMatch[1] : "";
  264. result = result.trim();
  265. }
  266. return result;
  267. }
  268. function getScriptReferenceHtml() { return `<a href="${getDownloadUrl()}" title="${isEn ? "Check for update" : "Проверить обновление скрипта"}" target=_blanc>${GM_info.script.name} ${GM_info.script.version}</a>`; }
  269. function getSendErrorMailReferenceHtml() { return `<a href="sms-create.php?mailto=${getScriptLastAuthor()}&subject=${isEn ? "Error in" : "Ошибка в"} ${GM_info.script.name} ${GM_info.script.version} (${GM_info.scriptHandler} ${GM_info.version})" target=_blanc>${isEn ? "Bug report" : "Сообщить об ошибке"}</a>`; }
  270. // Server time
  271. function getServerTime() { return Date.now() - parseInt(getValue("ClientServerTimeDifference", 0)); }
  272. function getGameDate() { return new Date(getServerTime() + 10800000); } // Игра в интерфейсе всегда показывает московское время // Это та дата, которая в toUTCString покажет время по москве
  273. function toServerTime(clientTime) { return clientTime - parseInt(GM_getValue("ClientServerTimeDifference", 0)); }
  274. function toClientTime(serverTime) { return serverTime + parseInt(GM_getValue("ClientServerTimeDifference", 0)); }
  275. function truncToFiveMinutes(time) { return Math.floor(time / 300000) * 300000; }
  276. function today() { const now = new Date(getServerTime()); now.setHours(0, 0, 0, 0); return now; }
  277. function tomorrow() { const today1 = today(); today1.setDate(today1.getDate() + 1); return today1; }
  278. async function requestServerTime() {
  279. if(parseInt(getValue("LastClientServerTimeDifferenceRequestDate", 0)) + 6 * 60 * 60 * 1000 < Date.now()) {
  280. setValue("LastClientServerTimeDifferenceRequestDate", Date.now());
  281. const responseText = await getRequestText("/time.php");
  282. const responseParcing = /now (\d+)/.exec(responseText); //responseText: now 1681711364 17-04-23 09:02
  283. if(responseParcing) {
  284. setValue("ClientServerTimeDifference", Date.now() - parseInt(responseParcing[1]) * 1000);
  285. }
  286. } else {
  287. setTimeout(requestServerTime, 60 * 60 * 1000);
  288. }
  289. }
  290. // dateString - игровое время, взятое со страниц игры. Оно всегда московское // Как результат возвращаем серверную дату
  291. function parseDate(dateString, isFuture = false, isPast = false) {
  292. //console.log(dateString)
  293. if(!dateString) {
  294. return;
  295. }
  296. const dateStrings = dateString.split(" ");
  297.  
  298. let hours = 0;
  299. let minutes = 0;
  300. let seconds = 0;
  301. const gameDate = getGameDate();
  302. let year = gameDate.getUTCFullYear();
  303. let month = gameDate.getUTCMonth();
  304. let day = gameDate.getUTCDate();
  305. const timePart = dateStrings.find(x => x.includes(":"));
  306. if(timePart) {
  307. var time = timePart.split(":");
  308. hours = parseInt(time[0]);
  309. minutes = parseInt(time[1]);
  310. if(time.length > 2) {
  311. seconds = parseInt(time[2]);
  312. }
  313. if(dateStrings.length == 1) {
  314. let result = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
  315. if(isPast && result > gameDate) {
  316. result.setUTCDate(result.getUTCDate() - 1);
  317. }
  318. if(isFuture && result < gameDate) {
  319. result.setUTCDate(result.getUTCDate() + 1);
  320. }
  321. //console.log(`result: ${result}, gameDate: ${gameDate}`)
  322. result.setUTCHours(result.getUTCHours() - 3);
  323. return result;
  324. }
  325. }
  326.  
  327. const datePart = dateStrings.find(x => x.includes("-"));
  328. if(datePart) {
  329. const date = datePart.split("-");
  330. month = parseInt(date[isEn ? (date.length == 3 ? 1 : 0) : 1]) - 1;
  331. day = parseInt(date[isEn ? (date.length == 3 ? 2 : 1) : 0]);
  332. if(date.length == 3) {
  333. const yearText = isEn ? date[0] : date[2];
  334. year = parseInt(yearText);
  335. if(yearText.length < 4) {
  336. year += Math.floor(gameDate.getUTCFullYear() / 1000) * 1000;
  337. }
  338. } else {
  339. if(isFuture && month == 0 && gameDate.getUTCMonth() == 11) {
  340. year += 1;
  341. }
  342. }
  343. }
  344. if(dateStrings.length > 2) {
  345. const letterDateExec = /(\d{2}):(\d{2}) (\d{2}) (.{3,4})/.exec(dateString);
  346. if(letterDateExec) {
  347. //console.log(letterDateExec)
  348. day = parseInt(letterDateExec[3]);
  349. //const monthNames = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря'];
  350. const monthShortNames = ['янв', 'фев', 'март', 'апр', 'май', 'июнь', 'июль', 'авг', 'сент', 'окт', 'ноя', 'дек'];
  351. month = monthShortNames.findIndex(x => x.toLowerCase() == letterDateExec[4].toLowerCase());
  352. if(isPast && Date.UTC(year, month, day, hours, minutes, seconds) > gameDate.getTime()) {
  353. year -= 1;
  354. }
  355. }
  356. }
  357. //console.log(`year: ${year}, month: ${month}, day: ${day}, time[0]: ${time[0]}, time[1]: ${time[1]}, ${new Date(year, month, day, parseInt(time[0]), parseInt(time[1]))}`);
  358. let result = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
  359. result.setUTCHours(result.getUTCHours() - 3);
  360. return result;
  361. }
  362. // Misc
  363. async function initUserName() {
  364. if(location.pathname == "/pl_info.php" && getUrlParamValue(location.href, "id") == PlayerId) {
  365. //console.log(document.querySelector("h1").innerText)
  366. setPlayerValue("UserName", document.querySelector("h1").innerText);
  367. }
  368. if(location.pathname == "/home.php") {
  369. //console.log(document.querySelector(`a[href='pl_info.php?id=${PlayerId}'] > b`).innerText)
  370. setPlayerValue("UserName", document.querySelector(`a[href='pl_info.php?id=${PlayerId}'] > b`).innerText);
  371. }
  372. if(!getPlayerValue("UserName")) {
  373. const doc = await getRequest(`/pl_info.php?id=${PlayerId}`);
  374. setPlayerValue("UserName", doc.querySelector("h1").innerText);
  375. }
  376. }
  377. function getUrlParamValue(url, paramName) { return (new URLSearchParams(url.split("?")[1])).get(paramName); }
  378. function showBigData(data) { console.log(data); /*addElement("TEXTAREA", { innerText: data }, document.body);*/ }
  379. function round0(value) { return Math.round(value * 10) / 10; }
  380. function round00(value) { return Math.round(value * 100) / 100; }
  381. function mobileCheck() {
  382. let check = false;
  383. (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
  384. return check;
  385. };
  386. // MutationObserver
  387. function observe(targets, handler, config = { childList: true, subtree: true }) {
  388. targets = Array.isArray(targets) ? targets : [targets];
  389. targets = targets.map(x => { if(typeof x === 'function') { return x(document); } return x; }); // Можем передавать не элементы, а их селекторы
  390. const ob = new MutationObserver(async function(mut, observer) {
  391. //console.log(`Mutation start`);
  392. observer.disconnect();
  393. if(handler.constructor.name === 'AsyncFunction') {
  394. await handler();
  395. } else {
  396. handler();
  397. }
  398. for(const target of targets) {
  399. if(target) {
  400. observer.observe(target, config);
  401. }
  402. }
  403. });
  404. for(const target of targets) {
  405. if(target) {
  406. ob.observe(target, config);
  407. }
  408. }
  409. }
  410. // UpdatePanels
  411. // Если используется url, то это должна быть та же локация с другими параметрами
  412. async function refreshUpdatePanels(panelSelectors, postProcessor, url = location.href) {
  413. panelSelectors = Array.isArray(panelSelectors) ? panelSelectors : [panelSelectors];
  414. let freshDocument;
  415. for(const panelSelector of panelSelectors) {
  416. const updatePanel = panelSelector(document);
  417. //console.log(panelSelector.toString())
  418. //console.log(updatePanel)
  419. if(updatePanel) {
  420. freshDocument = freshDocument || await getRequest(url);
  421. const freshUpdatePanel = panelSelector(freshDocument);
  422. if(!freshUpdatePanel) {
  423. console.log(updatePanel)
  424. continue;
  425. }
  426. if(postProcessor) {
  427. postProcessor(freshUpdatePanel);
  428. }
  429. updatePanel.innerHTML = freshUpdatePanel.innerHTML;
  430. Array.from(updatePanel.querySelectorAll("script")).forEach(x => {
  431. x.insertAdjacentElement("afterend", addElement("script", { innerHTML: x.innerHTML })); // Передобавляем скрипты, как элементы, что они сработали
  432. x.remove();
  433. });
  434. }
  435. }
  436. if(typeof win.hwm_hints_init === 'function') win.hwm_hints_init();
  437. return freshDocument;
  438. }