我正在尝试优化我在 phpBB3 上的“剧透”bbcode。
现在,我有一个可行的解决方案,但每次使用“剧透”bbcode 标签时,phpBB 都会注入(inject)内联 javascript。我想调用一个通用函数,而不是在每次使用 bbcode 时都内联添加它。
这是有效的内联 javascript:
<div class="spoiler">
<div class="spoiler-title">
<span onclick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.parentNode.getElementsByTagName('a')[0].innerText = 'hide'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.parentNode.getElementsByTagName('a')[0].innerText = 'show'; }">
<strong>{TEXT1}</strong> (<a href="#" class="spoiler-btn" title="Show hidden content">show</a>)
</span>
</div>
<div class="spoiler-text">
<div style="display: none;">
{TEXT2}
</div>
</div>
</div>
为了阅读方便,这里重复了内联的onclick函数:
if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') {
this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = '';
this.parentNode.getElementsByTagName('a')[0].innerText = 'hide';
} else {
this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none';
this.parentNode.getElementsByTagName('a')[0].innerText = 'show';
}
点击“spoiler-btn”类的 anchor 有一个preventDefaults,以防止点击将您带到页面顶部:
$(document).ready(function(){
$(".spoiler-btn").click(
function(e) {
e.preventDefault();
}
);
});
我试图用将“this”传递给外部 javascript 文件的函数调用替换 span onclick 内联 javascript。我似乎无法让它工作,所以我尝试使用 jQuery 捕获“this”以遍历 DOM 以找到包含在“spoiler-text”div 中的“div”并操纵显示:无。页面上可以有多个剧透标签,所以我不能给“剧透文本”div 内的 div 一个 id。
这里我把span的onclick改成了外部函数:
onclick="spoilerToggle(this);"
然后我的外部文件中有以下内容:
var spoilerToggle = function(param) {
if ($(this).parent('div').parent('div').hasClass('spoiler-text').css('style') == 'none') {
($(this).parent('div').parent('div').hasClass('spoiler-text').removeAttr('style'));
($(this).parent('div').$('a').text('hide'));
} else {
($(this).parent('div').parent('div').hasClass('spoiler-text').css('display', 'none'));
($(this).parent('div').$('a').text('show'));
}
}
然后控制台给出以下错误: bbcode.js:22 Uncaught TypeError: $(...).parent(...).parent(...).hasClass(...).css 不是函数
第 22 行是带有“if”检查的行。
jQuery 已加载到网站上,并且我确保在 body 标记结束之前调用我的外部 javascript 文件。
我觉得自己掉进了兔子洞,看不到光。我确信这比我想象的要容易得多。
非常感谢任何帮助。谢谢!
最佳答案
.hasClass()
返回一个 bool 值,所以你不能在它后面链接其他方法。这就是为什么你得到你引用的错误。
不过我会以不同的方式实现它:
$(document).on("click", ".spoiler-title", function(e) {
e.preventDefault();
var container = $(this).closest(".spoiler");
container.find(".spoiler-btn").text(function(i, currentText) {
return currentText === "show" ? "hide" : "show"
});
container.find(".spoiler-text div").toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="spoiler">
<div class="spoiler-title">
<span>
<strong>{TEXT1}</strong> (<a href="#" class="spoiler-btn" title="Show hidden content">show</a>)
</span>
</div>
<div class="spoiler-text">
<div style="display: none;">
{TEXT2}
</div>
</div>
</div>
上面使用绑定(bind)到文档的单个委托(delegate)点击处理程序来处理页面上所有剧透元素的点击(您可以将它绑定(bind)到较低级别的容器元素,无论最低级别是包含所有剧透)。
在处理程序中,this
将引用被点击的元素,因此对于 DOM 导航方法,例如 .closest()
和 .find()
您可以向上移动到包含的 div,然后向下移动到您想要操作的元素。 .closest()
比尝试链接 .parent().parent()
更灵活,因为它会自动上升,直到找到与指定选择器匹配的元素,因此,如果您以后更改 HTML 结构,则 JS 可能不需要更改。
如果.text()
调用看起来令人困惑,jQuery 调用我作为参数传递给 .text()
的函数,将元素文本的当前值传递给它,然后返回的任何值都成为新文本。
关于javascript - 将内联 javascript 函数移动到外部文件并转换为 jQuery,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46721768/