jQuery 內建 :contains(text) 選擇器可依元素文字內容篩選,但部分精簡版或舊版未包含。本文示範如何以原生 JavaScript 實作相同功能,並封裝為 jQuery 插件擴展。
function yhCheckIsIncludingValue(element, pattern) {
// 文字節點直接比對
if (element.nodeType === Node.TEXT_NODE) {
return pattern.test(element.nodeValue);
}
// 元素節點遞迴檢查子節點
if (element.nodeType === Node.ELEMENT_NODE) {
const children = element.childNodes;
for (let i = 0; i < children.length; i++) {
if (yhCheckIsIncludingValue(children[i], pattern)) {
return true;
}
}
}
return false;
}
採用深度優先遞迴遍歷 DOM 樹,支援巢狀結構。使用 RegExp 物件進行大小寫不敏感比對。
(function($) {
$.fn.contains = function(text) {
text = $.trim(text);
if (!text || text === 'undefined') return this;
const pattern = new RegExp(text, 'i'); // i: 不分大小寫
return this.filter(function() {
return yhCheckIsIncludingValue(this, pattern);
});
};
})(jQuery);
<ul id="list">
<li>蘋果汁</li>
<li>香蕉牛奶</li>
<li><span>柳橙</span>茶</li>
<li>葡萄醋</li>
</ul>
<script>
// 找出包含「橙」的 li,並加上高亮
$('#list li').contains('橙').css('background', '#ffff00');
// 結果:第 3 項「柳橙茶」會被選中
</script>
Node.TEXT_NODE、childNodes、RegExpNode.TEXT_NODE 改為數值 3,Node.ELEMENT_NODE 改為 1es5-shim 或改用 element.innerText/textContent 簡化實作element.textContent.indexOf(text) !== -1 快速初篩,再精確比對RegExp 物件避免重複編譯TreeWalker API 替代手寫遞迴,瀏覽器原生實現更高效$.fn.containsAny = function(...texts) {
const patterns = texts.map(t => new RegExp($.trim(t), 'i'));
return this.filter(function() {
return patterns.some(p => yhCheckIsIncludingValue(this, p));
});
};
$.fn.containsAll = function(...texts) {
const patterns = texts.map(t => new RegExp($.trim(t), 'i'));
return this.filter(function() {
return patterns.every(p => yhCheckIsIncludingValue(this, p));
});
};