jQuery Selector不合用? 自己寫一個吧!
3 |
在先前文章的留言討論中,引出了一個有趣話題。
jQuery的Selector種類繁多,神奇又好用,但在某些情境下還是可能找不到100%符合需求的。像是:contains()可以用來比對"文字內容包含某個字串",但如果我們要的是"文字內容完全等於某個字串"或是"文字內容完全等於某個字串,但不用分大小寫",要怎麼辦?
先假設情境是要找出所有文字內容恰等於"Darkthread"的<a>,例如: <a href="..." mce_href="...">Darkthread</a>,如果用$("a:contains('Darkthread')")則連<a href="..." mce_href="...">Fake Darkthread</a>也會被算進來。
一個簡單且直覺的方法是利用filter函數:
$("a").filter(function() { return $(this).text() == "Darkthread" });
但有更巧妙的做法--Selector不合用? 那就自己寫一個! jQuery在架構上已預留可自行擴充Selector的空間,要擴充很簡單。說到這裡,大家對jQuery的景仰是否已如濤濤江水?
假設我們對:contains()的"包含"特性不滿意,我們打算生出另一個:exact('...')的Selector,限定文字內容要完全相符才算數,只需要一行Code:
$.extend($.expr[":"], { exact: "(a.textContent||a.innerText||jQuery(a).text()||'') == m[3];" });
接著就可以用$("a:exact('Darkthread')")來找出文字完全吻合Darkthread的<a>了。
回頭來看一下要自訂Selector的設定語法
$.extend($.expr[":"], { filterName: filterEvalExpression });
其中filterName是要自訂的Selector Filter名稱,filterEvalExpression的字串內容則是一個邏輯運算式,用以傳回true或false,而在運算式中,我們有幾個預設變數可用:
- a 比對的DOM元素物件
- i 元素在查詢結果的排序位置
- m 拆解Selector而成的字串陣列,當Filter是:exact('aaa')時,可利用m[3]取得aaa,作為比對之用。
有興趣深入研究的人可以參考jquery.js裡的Filter寫法,應該很快就能照著研發出自己想要的Selector。
至於不分大小寫的比對,相信難不倒大家吧:
$.extend($.expr[":"], { exactCI: "(a.textContent||a.innerText||jQuery(a).text()||'').toLowerCase() == m[3].toLowerCase();" });
【2009-01-31更新】jQuery 1.3中無法直接以字串表示過濾邏輯,需寫成$.extend($.expr[":"], { exact: function(a, i, m) { return (a.textContent || a.innerText || jQuery(a).text() || '') == m[3]; } }); 詳細說明
Comments
# by 阿珂~
:contains 好無法選擇到中文,不曉得有沒有解決的方式呢?
# by 阿珂~
hi~ 我發現問題了! 將:contains寫到.js的檔案中,讓html外掛讀取時,會找不到中文。 不過直接將:contains寫在html的<head></head>中就可以嘍!
# by Jeffrey
to 阿珂,感覺上是js Encoding問題,可以參考這篇http://blog.darkthread.net/blogs/darkthreadtw/archive/2007/05/04/747.aspx