JavaScript卡牌生成代码故障排查:重复生成/tooltip失效等问题
我帮你排查了代码里的三个问题,咱们一个个来解决:
问题1:生成2张卡牌而非1张
原因:你的代码同时绑定了$(window).load()和$(function())(DOM就绪事件),这两个事件都会触发内容替换逻辑,导致同一个#myluckynumberis(\d+)标签被替换两次,生成两张重复卡牌。
修复方法:合并事件处理逻辑,只保留一个DOM就绪的入口。推荐用$(function()),它在DOM结构加载完成后就执行,比window.load更早,用户体验更好。
问题2:首张卡牌开头显示>,鼠标悬浮提示tagged with: div class=
原因:你构建HTML字符串时误用了<和>(HTML转义字符),这些字符插入DOM时会被当作普通文本解析,而非HTML标签。比如<div会变成文本<div,导致浏览器解析出错,出现多余的>和错误的tooltip提示。
修复方法:直接使用<和>构建HTML标签即可——因为我们是通过JavaScript生成HTML字符串后插入DOM,不需要在字符串里做HTML转义。
问题3:Tooltip功能失效
原因:你设置data-tooltip属性时写了data-tooltip="' + '",这会让属性值为空,Tooltip自然无法正常工作。需要把英雄详情的内容或跳转逻辑填入这个属性。
修复方法:将data-tooltip设置为实际的提示内容,比如英雄名称或详情说明(如果需要跳转,可以结合点击事件或让Tooltip包含链接,具体取决于你的Tooltip实现逻辑)。
修复后的完整代码
$(function() { //======== CARD MAKER FUNCTION ========== function make_card_list(card, el) { var html = ''; // 修复:直接用<和>构建HTML标签,移除转义字符 html += '<div class="card" id="card_' + card.id + '">'; html += '<span class="card_id">#superhero' + card.id + '</span>'; html += '<div class="card_header">'; html += '<span data-name="name">' + card.name + '</span>'; html += '</div>'; html += '<div class="abilities-details">' + card.abilities + '</div>'; // 修复:设置有效的Tooltip内容,这里用英雄名称示例,可按需修改 html += '<div data-tooltip="查看英雄详情:' + card.name + '" class="card_picture" data-name="img" style="background-image: url(' + card.img + ');text-align:center;color:black;line-height: 150px;">'; var poster_data = $(el).parent().parent().find('.postprofile textarea').val(); if (poster_data) { poster_data = JSON.parse(poster_data); if (jQuery.inArray(Number(card.id), poster_data.cards) == -1) { html += '<div class="nocard">This card does not exit.</div>'; } } html += '</div>'; html += '<div class="card_text">'; html += '<span data-name="txt">'; html += card.txt; html += '</span>'; html += '</div>'; html += '<div class="abilities"></div>'; html += '<div class="card_bottom card_stats">'; html += '<div class="card_stats_inside">'; if (card.strength != "") { html += '<p>Strength: <span data-name="strength">' + card.strength + '</span></p>'; }; if (card.energy != "") { // 修复:data-name写错,从damage改为energy html += '<p>Energy: <span data-name="energy">' + card.energy + '</span></p>'; }; if (card.skills != "") { // 修复:data-name写错,从damage改为skills html += '<p>Skills: <span data-name="skills">' + card.skills + '</span></p>'; }; if (card.speed != "") { // 修复:data-name写错,从damage改为speed html += '<p>Speed: <span data-name="speed">' + card.speed + '</span></p>'; }; html += '</div>'; html += '</div>'; if (card.type == 16 || card.type == 14 || card.type == 31 || card.type == 27) { html += '<div class="card_bottom card_slots" style="width:335px;">'; html += '<div class="card_slots_inside">'; if (card.inv > 0) { for (var i = 0; i < 10; i++) { if (i < card.inv) { html += '<span style="background:#9d1717;" class="card_inv"></span>'; } else { html += '<span class="card_inv"></span>'; } } } html += '<span style="background: #57b371;" class="card_slot"></span>'; } else { html += '<div class="card_bottom card_middle">'; html += '<div class="card_stats_inside">'; if (card.enemies != "") { html += '<p>Enemies: <span data-name="enemies">' + card.enemies + '</span></p>'; }; html += '</div>'; html += '</div>'; html += '<div class="card_bottom card_slots">'; html += '<div class="card_slots_inside">'; if (Number(card.slot) > 0) { for (var i = 0; i < 5; i++) { if (i < card.slot) { html += '<span style="background: #57b371;" class="card_slot"></span>'; } else { html += '<span class="card_slot"></span>'; } } } } html += '</div>'; html += '</div>'; html += '</div>'; if (card.type == 16 || card.type == 14 || card.type == 31 || card.type == 27) { $('#card_' + card.id + ' .card_middle').remove(); $('#card_' + card.id + ' .card_slots').css('width', '335px'); } return html; } //======== CARD MANAGER ========== function sortCards(ar, s, t) { var results = []; ar.find(function(ele) { if (ele[t] == s) { results.push(ele); } }); return results; } $(" .pun .entry-content, .pravilacontent div").each(function() { var h = ''; $('img[src^="#card"]', this).each(function() { var npccard = $(this).attr('src'); if (npccard != null) { // 原代码此处为空,可补充你需要的逻辑 } }); if (h != '') { $(this).parent().parent().find('.topic-title a').text('NPC Attack'); $(this).html(h); } var content = $(this).html(); var el = $(this); content = content.replace(/#myluckynumberis(\d+)/g, function(match, capture) { if (!cards[capture]) { return "myluckynumberis #" + capture + " does not exists"; } return make_card_list(sortCards(cards, capture, "id")[0], el); }); $(this).html(content); }); // 合并原有的论坛版本检测逻辑 var version = "punbb"; if (version.toLowerCase() == "phpbb2") { $(" .postdetails span[class='staff']").closest('.postdetails').parent('td').next('td').addClass("staffbg"); } else if (version.toLowerCase() == "phpbb3") { $(" .postprofile span[class='staff']").closest('.postprofile').prev('.postbody').addClass("staffbg"); } else if (version.toLowerCase() == "punbb") { $(" .user-info span[class='staff']").closest('.postmain').addClass("staffbg"); } else if (version.toLowerCase() == "invision") { $(" .postprofile span[class='staff']").closest('.post-container').addClass("staffbg"); } }); // 注意:jQuery需在代码前引入,例如放在HTML的<head>标签内 // <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
额外说明:我还修复了代码里的一个小bug——card.energy、card.skills、card.speed对应的data-name都误写为damage,这会导致后续基于data-name的操作失效,现已修正为对应的属性名。
内容的提问来源于stack exchange,提问作者skouliki

