Mediawiki:common.js

Вернуться

Строка 1: Строка 1:
/**
* Если CDN недоступен: залей на вики popper.min.js, tippy-bundle.umd.min.js, tippy.css (через Загрузить файл),
* затем в консоли или в начале скрипта задай:
*  MediaWikiTooltips.baseUrl = "https://fire.station.wiki.shizainc.com/wiki/Special:FilePath/";
* (подставь свой домен вики)
*/
(function () {
(function () {
     "use strict";
     "use strict";
Строка 26: Строка 32:
                     tippy: "/tippy.js/6.3.7/tippy-bundle.umd.min.js",
                     tippy: "/tippy.js/6.3.7/tippy-bundle.umd.min.js",
                     css: "/tippy.js/6.3.7/tippy.css",
                     css: "/tippy.js/6.3.7/tippy.css",
                },
                {
                    base: "https://unpkg.com",
                    popper: "/@popperjs/core@2/dist/umd/popper.min.js",
                    tippy: "/tippy.js@6/dist/tippy-bundle.umd.min.js",
                    css: "/tippy.js@6/dist/tippy.css",
                },
                {
                    base: "https://cdn.jsdelivr.net/npm",
                    popper: "/@popperjs/core@2/dist/umd/popper.min.js",
                    tippy: "/tippy.js@6/dist/tippy-bundle.umd.min.js",
                    css: "/tippy.js@6/dist/tippy.css",
                 },
                 },
             ];
             ];
Строка 62: Строка 56:
                 self.loading = false;
                 self.loading = false;
                 self.callbacks.forEach(function (cb) {
                 self.callbacks.forEach(function (cb) {
                     try {
                     try { cb(); } catch (e) {}
                        cb();
                    } catch (e) {
                        console.error("[MediaWikiTooltips] callback error:", e);
                    }
                 });
                 });
                 self.callbacks = [];
                 self.callbacks = [];
Строка 82: Строка 72:
                     if (cdnIndex + 1 < cdns.length) {
                     if (cdnIndex + 1 < cdns.length) {
                         cdnIndex++;
                         cdnIndex++;
                        console.warn(
                            "[MediaWikiTooltips] Повтор с CDN:",
                            cdns[cdnIndex].base,
                        );
                         loadPopper();
                         loadPopper();
                     } else {
                     } else {
Строка 104: Строка 90:
                     tippyCSS.rel = "stylesheet";
                     tippyCSS.rel = "stylesheet";
                     tippyCSS.href = urlJoin(cdn.base, cdn.css);
                     tippyCSS.href = urlJoin(cdn.base, cdn.css);
                     tippyCSS.onerror = function () {
                     tippyCSS.onerror = function () {};
                        console.warn(
                            "[MediaWikiTooltips] Стили Tippy не загрузились.",
                        );
                    };
                     document.head.appendChild(tippyCSS);
                     document.head.appendChild(tippyCSS);
                    console.log(
                        "[MediaWikiTooltips] Tippy.js загружен с",
                        cdn.base,
                    );
                     runCallbacks();
                     runCallbacks();
                 };
                 };
Строка 126: Строка 104:
                     if (cdnIndex + 1 < cdns.length) {
                     if (cdnIndex + 1 < cdns.length) {
                         cdnIndex++;
                         cdnIndex++;
                        console.warn(
                            "[MediaWikiTooltips] Повтор с CDN:",
                            cdns[cdnIndex].base,
                        );
                         loadPopper();
                         loadPopper();
                     } else {
                     } else {
Строка 220: Строка 194:


     var LawTooltipsModule = {
     var LawTooltipsModule = {
         init: function () {
         init: function() {
            console.log("[LawTooltips] init()");
             var tableCells = document.querySelectorAll('.law-tooltips td, .law-tooltips th');
             var tableCells = document.querySelectorAll(
             if (tableCells.length === 0) return;
                ".law-tooltips td, .law-tooltips th",
              
            );
             MediaWikiTooltips.load(function() {
            console.log(
                "[LawTooltips] .law-tooltips ячеек:",
                tableCells.length,
            );
             if (tableCells.length === 0) {
                console.warn("[LawTooltips] Нет ячеек .law-tooltips — выход");
                return;
             }
 
             function run() {
                console.log("[LawTooltips] run() — извлечение данных...");
                 var lawData = LawTooltipsModule.extractLawData();
                 var lawData = LawTooltipsModule.extractLawData();
                 var count = Object.keys(lawData).length;
                 LawTooltipsModule.initCellTooltips(tableCells, lawData);
                console.log(
                    "[LawTooltips] Загружено записей законов:",
                    count,
                    count
                        ? Object.keys(lawData).slice(0, 10).join(", ") +
                              (count > 10 ? "..." : "")
                        : "",
                );
                if (count > 0) {
                    LawTooltipsModule.initCellTooltips(tableCells, lawData);
                    return true;
                }
                return false;
            }
 
            if (typeof MediaWikiTooltips === "undefined") {
                console.error(
                    "[LawTooltips] MediaWikiTooltips не найден — тултипы не загрузятся",
                );
                run();
                return;
            }
            MediaWikiTooltips.load(function () {
                console.log("[LawTooltips] MediaWikiTooltips.load вызван");
                if (run()) {
                    console.log("[LawTooltips] Инициализация с первой попытки");
                    return;
                }
                setTimeout(function () {
                    if (run()) {
                        console.log("[LawTooltips] Инициализация после 300ms");
                        return;
                    }
                    setTimeout(function () {
                        if (run())
                            console.log(
                                "[LawTooltips] Инициализация после 800ms",
                            );
                        else
                            console.warn(
                                "[LawTooltips] Данные законов не найдены после всех попыток",
                            );
                    }, 500);
                }, 300);
             });
             });
         },
         },
 
       
         extractLawData: function () {
         extractLawData: function() {
            var lawData = {};
    var lawData = {};
            var containers = document.querySelectorAll(".mw-collapsible");
    var detailTables = document.querySelectorAll('.mw-collapsible-content table');
            console.log(
   
                "[LawTooltips] extractLawData: коллапсибл-блоков:",
    detailTables.forEach(function(table) {
                containers.length,
        var rows = table.querySelectorAll('tr');
            );
       
            containers.forEach(function (block) {
        rows.forEach(function(row) {
                var content = block.querySelector(".mw-collapsible-content");
            var cells = row.querySelectorAll('td');
                if (content && block.classList.contains("mw-collapsed")) {
            if (cells.length < 3) return;
                    block.classList.remove("mw-collapsed");
           
                    var toggle = content.querySelector(
            var crimeCell = cells[0];
                        ".mw-collapsible-toggle",
            var descriptionCell = cells[1];
                    );
            var exampleCell = cells[2];
                    if (toggle) toggle.setAttribute("aria-expanded", "true");
           
                }
            var anchor = crimeCell.querySelector('[id]');
            });
            if (!anchor) return;
 
           
            var detailTables = document.querySelectorAll(
            var lawCode = anchor.id;
                ".mw-collapsible-content table",
            var titleElement = crimeCell.querySelector('b');
            );
           
            console.log(
            if (titleElement && lawCode.match(/^\d{3}$/)) {
                "[LawTooltips] extractLawData: таблиц в .mw-collapsible-content:",
                var titleText = titleElement.textContent.trim();
                detailTables.length,
                var lawTitle = titleText.replace(/^\d{3}\s*/, '').replace(/^\d{3}/, '').trim();
            );
                var description = descriptionCell.innerHTML.trim();
            detailTables.forEach(function (table, tableIndex) {
               
                if (table.classList.contains("law-tooltips")) {
                var examples = [];
                    console.log(
                var exampleItems = exampleCell.querySelectorAll('li');
                        "[LawTooltips] extractLawData: таблица",
exampleItems.forEach(function(item) {
                        tableIndex,
    var html = item.innerHTML.trim();
                        "— пропуск (law-tooltips)",
    // Удаляем все <br> теги
                    );
    html = html.replace(/<br\s*\/?>/gi, '');
                    return;
    if (html) examples.push(html);
                }
});
                var rows = table.querySelectorAll("tr");
               
 
                lawData[lawCode] = {
                rows.forEach(function (row) {
                    title: lawTitle,
                    var cells = row.querySelectorAll("td");
                    description: description,
                    if (cells.length < 3) return;
                    examples: examples
 
                };
                    var crimeCell = cells[0];
            }
                    var descriptionCell = cells[1];
        });
                    var exampleCell = cells[2];
    });
 
   
                    var anchor = crimeCell.querySelector("[id]");
    return lawData;
                    if (!anchor) return;
},
 
       
                    var lawCode = anchor.id;
    createTooltipContent: function(lawCode, lawData) {
                    var titleElement = crimeCell.querySelector("b");
    var data = lawData[lawCode];
                    if (!titleElement || !lawCode.match(/^\d{3}$/)) return;
    if (!data) return null;
 
   
                    var titleText = titleElement.textContent.trim();
    var html = '<div class="law-tooltip">';
                    var lawTitle = titleText
    html += '<h4 class="law-tooltip-title">' + lawCode + ' - ' + data.title + '</h4>';
                        .replace(/^\d{3}\s*/, "")
    html += '<p class="law-tooltip-description">' + data.description + '</p>';
                        .replace(/^\d{3}/, "")
   
                        .trim();
    if (data.examples && data.examples.length > 0) {
                    var description = descriptionCell.innerHTML.trim();
        html += '<div class="law-tooltip-examples">';
 
        html += '<strong>Примеры:</strong><ul>';
                    var examples = [];
        data.examples.slice(0, 5).forEach(function(example) {
                    var exampleItems = exampleCell.querySelectorAll("li");
            html += '<li>' + example + '</li>'; // Теперь example содержит HTML
                    exampleItems.forEach(function (item) {
        });
                        var html = item.innerHTML
        html += '</ul></div>';
                            .trim()
    }
                            .replace(/<br\s*\/?>/gi, "");
    html += '</div>';
                        if (html) examples.push(html);
   
                    });
    return html;
 
},
                    lawData[lawCode] = {
       
                        title: lawTitle,
         initCellTooltips: function(tableCells, lawData) {
                        description: description,
             tableCells.forEach(function(cell) {
                        examples: examples,
                 var link = cell.querySelector('a[href*="#"]');
                    };
                 if (!link) return;
                });
                  
            });
                 var href = link.getAttribute('href');
 
                 var match = href.match(/#(\d{3})/);
            console.log(
                 if (!match) return;
                "[LawTooltips] extractLawData: итого кодов:",
                  
                Object.keys(lawData).length,
                 var lawCode = match[1];
            );
                 var tooltipContent = LawTooltipsModule.createTooltipContent(lawCode, lawData);
            return lawData;
                 if (!tooltipContent) return;
        },
                  
 
                 cell.classList.add('law-cell-with-tooltip');
        createTooltipContent: function (lawCode, lawData) {
                  
            var data = lawData[lawCode];
                 cell.addEventListener('click', function(e) {
            if (!data) return null;
                     e.preventDefault();
 
                     window.location.hash = lawCode;
            var html = '<div class="law-tooltip">';
                 });
            html +=
                  
                '<h4 class="law-tooltip-title">' +
                 tippy(cell, {
                lawCode +
                     content: tooltipContent,
                " - " +
                     allowHTML: true,
                data.title +
                     interactive: true,
                "</h4>";
                     placement: 'top',
            html +=
                     maxWidth: 400,
                '<p class="law-tooltip-description">' +
                     theme: 'law-theme',
                data.description +
                     arrow: true,
                "</p>";
                     duration: [200, 150],
 
                     delay: [0, 50],
            if (data.examples && data.examples.length > 0) {
                     appendTo: document.body,
                html += '<div class="law-tooltip-examples">';
                     boundary: 'viewport',
                html += "<strong>Примеры:</strong><ul>";
                     popperOptions: {
                data.examples.slice(0, 5).forEach(function (example) {
                         strategy: 'fixed',
                    html += "<li>" + example + "</li>";
                         modifiers: [
                });
                             {
                html += "</ul></div>";
                                 name: 'preventOverflow',
            }
                                 options: {
            html += "</div>";
                                     boundary: 'viewport',
 
                                     padding: 20,
            return html;
                                     altAxis: true,
        },
                                     altBoundary: true
 
                                 }
         initCellTooltips: function (tableCells, lawData) {
                             },
            var withLink = 0,
                             {
                withMatch = 0,
                                 name: 'flip',
                withContent = 0,
                                 options: {
                tooltipsCreated = 0;
                                     fallbackPlacements: ['bottom', 'left', 'right']
             tableCells.forEach(function (cell) {
                                 }
                 var link = cell.querySelector('a[href*="#"]');
                             },
                 if (!link) return;
                             {
                 withLink++;
                                 name: 'computeStyles',
 
                                 options: { adaptive: false }
                 var href = link.getAttribute("href");
                             }
                 var match = href.match(/#(\d{3})/);
                         ]
                 if (!match) return;
                     },
                 withMatch++;
                     onShow: function(instance) {
 
                         document.querySelectorAll('[data-tippy-root]').forEach(function(tooltip) {
                 var lawCode = match[1];
                            if (tooltip._tippy && tooltip._tippy !== instance) {
                 var tooltipContent = LawTooltipsModule.createTooltipContent(
                                tooltip._tippy.hide();
                    lawCode,
                            }
                    lawData,
                        });
                );
                     }
                 if (!tooltipContent) return;
                 withContent++;
 
                 cell.classList.add("law-cell-with-tooltip");
                 tooltipsCreated++;
 
                 cell.addEventListener("click", function (e) {
                     e.preventDefault();
                     window.location.hash = lawCode;
                 });
 
                 if (typeof tippy === "undefined") {
                    console.error(
                        "[LawTooltips] tippy не найден — подключи библиотеку Tippy.js",
                    );
                    return;
                }
                 tippy(cell, {
                     content: tooltipContent,
                     allowHTML: true,
                     interactive: true,
                     placement: "top",
                     maxWidth: 400,
                     theme: "law-theme",
                     arrow: true,
                     duration: [200, 150],
                     delay: [0, 50],
                     appendTo: document.body,
                     boundary: "viewport",
                     popperOptions: {
                         strategy: "fixed",
                         modifiers: [
                             {
                                 name: "preventOverflow",
                                 options: {
                                     boundary: "viewport",
                                     padding: 20,
                                     altAxis: true,
                                     altBoundary: true,
                                 },
                             },
                             {
                                 name: "flip",
                                 options: {
                                     fallbackPlacements: [
                                        "bottom",
                                        "left",
                                        "right",
                                    ],
                                 },
                             },
                             {
                                 name: "computeStyles",
                                 options: { adaptive: false },
                             },
                         ],
                     },
                     onShow: function (instance) {
                         document
                            .querySelectorAll("[data-tippy-root]")
                            .forEach(function (tooltip) {
                                if (
                                    tooltip._tippy &&
                                    tooltip._tippy !== instance
                                ) {
                                    tooltip._tippy.hide();
                                }
                            });
                     },
                 });
                 });
             });
             });
            console.log(
         }
                "[LawTooltips] initCellTooltips: ячеек с ссылкой",
                withLink,
                "| с #XXX",
                withMatch,
                "| с данными",
                withContent,
                "| тултипов создано",
                tooltipsCreated,
            );
         },
     };
     };


Строка 1297: Строка 1137:
             );
             );
             var categories = {};
             var categories = {};
            console.log(
                "LawCalculator: Найдено секций с наказаниями:",
                punishmentSections.length,
            );
            console.log("LawCalculator: Тип страницы:", this.pageType);


             punishmentSections.forEach(
             punishmentSections.forEach(
Строка 1313: Строка 1147:
                     if (punishmentMatch) {
                     if (punishmentMatch) {
                         var punishmentText = punishmentMatch[1].trim();
                         var punishmentText = punishmentMatch[1].trim();
                        console.log(
                            "LawCalculator: Найдено наказание:",
                            punishmentText,
                        );


                         var categoryInfo =
                         var categoryInfo =
Строка 1327: Строка 1157:
                             if (categoryKey) {
                             if (categoryKey) {
                                 categories[categoryKey] = categoryInfo;
                                 categories[categoryKey] = categoryInfo;
                                console.log(
                                    "LawCalculator: Применено к категории:",
                                    categoryKey,
                                    categoryInfo,
                                );
                             }
                             }
                         }
                         }
Строка 1337: Строка 1162:
                 }.bind(this),
                 }.bind(this),
             );
             );
            console.log("LawCalculator: Итоговые категории:", categories);


             // Применяем найденную информацию к законам
             // Применяем найденную информацию к законам
Строка 2377: Строка 2200:


                 if (!FireworksConstructor) {
                 if (!FireworksConstructor) {
                    console.error(
                        "Не удалось найти конструктор Fireworks. Проверьте загрузку библиотеки.",
                    );
                    console.log("Доступные объекты:", {
                        "window.Fireworks": window.Fireworks,
                        "window.Fireworks.default":
                            window.Fireworks && window.Fireworks.default,
                        "window.fireworks": window.fireworks,
                    });
                     return;
                     return;
                 }
                 }