I'm using an extension for jQuery "contains", shown below:
$.extend($.expr[':'],{
containsExact: function(a,i,m){
return $.trim(a.innerHTML.toLowerCase()) === m[3].toLowerCase();
},
containsExactCase: function(a,i,m){
return $.trim(a.innerHTML) === m[3];
},
containsRegex: function(a,i,m){
var regreg = /^\/((?:\\\/|[^\/])+)\/([mig]{0,3})$/,
reg = regreg.exec(m[3]);
return RegExp(reg[1], reg[2]).test($.trim(a.innerHTML));
}
});
I have a table with certain cells that I'm trying to format conditionally, so I'm using the extension in a td
selector, with the containsRegex
function. The problem that I'm running into is that many of the regular expressions that I'm trying to use (which I've tested out on javascript regex testers like this and they've worked) do not work with this function. These are the various strings that I'd like to match:
Note that a "x" could be a x,t,f or v and an "X" could be an X,T,F or V. Lastly an "(mb)" could be any two lower case letters a-z in parenthesis.
-, (mb), x*, x*(mb), x, x(mb), X*, X*(mb), X
And here is the code with several of the regex statements that I'm using:
$("td:containsExact('-')").addClass("0 queue"); // -
$("td:containsRegex('/[^xtfv*]\([a-z]{2}\)/g')").addClass("1 active"); // (mb)
$("td:containsRegex('/\b[xtfv]\*(?!\()/g')").addClass("2 queue review"); // x*
$("td:containsRegex('/\b[xtfv]\*(?:\([a-z]{2}\))/g')").addClass("3 active review"); // x*(mb)
$("td:containsRegEx('/\b[xtfv](?![*\(])/g')").addClass("4 queue"); // x
$("td:containsRegEx('/\b[xtfv](?:\([a-z]{2}\))/g')").addClass("5 active"); // x(mb)
$("td:containsRegEx('/\b[XTFV]\*(?!\()/g')").addClass("6 queue review"); // X*
$("td:containsRegEx('/\b[XTFV]\*(?:\([a-z]{2}\))/g')").addClass("7 active review"); // X*(mb)
$("td:containsRegEx('/\b[XTFV](?![*\(])/g')").addClass("8 done"); // X
Most of these pass errors in Chrome. Does anyone have any pointers? Is the contains extension limited somehow?
Thanks in advance for your help!
Ok, I think I got it... These are the changes I made:
I changed the containsRegex a tiny bit by adding a "reg" check in the return, to make it more sturdy:
containsRegex: function(a,i,m){
var regreg = /^\/((?:\\\/|[^\/])+)\/([mig]{0,3})$/,
reg = regreg.exec(m[3]);
return reg ? RegExp(reg[1], reg[2]).test($.trim(a.innerHTML)) : false;
}
All escaped characters in the regex need to be double escaped ( i.e. \(
needs to be \\(
)
I removed all the single quotes to actually help me from being distracted
I removed the class name numbers. I know ID's shouldn't start with numbers and I'm pretty sure class names shouldn't start or only be a number either. Anyway, this led to some selectors adding the same regex (i.e. "x" and "-" look the same, as well as "x*(mb)" and "X*(mb)" with the css in the demo).
Anyway, I'll update my gist with this code and your demo:
/* jQuery selector to match exact text inside an element
* :containsExact() - case insensitive
* :containsExactCase() - case sensitive
* :containsRegex() - set by user ( use: $(el).find(':containsRegex(/(red|blue|yellow)/gi)') )
*/
$.extend($.expr[':'],{
containsExact: function(a,i,m){
return $.trim(a.innerHTML.toLowerCase()) === m[3].toLowerCase();
},
containsExactCase: function(a,i,m){
return $.trim(a.innerHTML) === m[3];
},
containsRegex: function(a,i,m){
var regreg = /^\/((?:\\\/|[^\/])+)\/([mig]{0,3})$/,
reg = regreg.exec(m[3]);
return reg ? RegExp(reg[1], reg[2]).test($.trim(a.innerHTML)) : false;
}
});
// -, (mb), x*, x*(mb), x, x(mb), X*, X*(mb), X
$("td:containsRegex(/^[xtfv]$/)").addClass("queue"); // x
$("td:containsRegex(/^[xtfv]\\*$/)").addClass("queue review"); // x*
$("td:containsRegex(/^\\([a-z]{2}\\)$/)").addClass("active"); // (mb)
$("td:containsRegex(/^[xtfv]\\([a-z]{2}\\)$/)").addClass("active"); // x(mb)
$("td:containsRegex(/^[xtfv]\\*\\([a-z]{2}\\)$/)").addClass("active review"); // x*(mb)
$("td:containsRegex(/^[XTFV]$/)").addClass("done"); // X
$("td:containsRegex(/^[XTFV]\\*$/)").addClass("queue review"); // X*
$("td:containsRegex(/^[XTFV]\\*\\([a-z]{2}\\)$/)").addClass("active review"); // X*(mb)
$("td:containsExact(-)").addClass("queue"); // -
"td:containsRegex('/\b[xtfv]\*(?!\()/g')"
\b
inside a string literal means backspace ("\b" === "\x08"
) whereas it means wordbreak in a regex. Try replacing all the \b
with \\b
.
You should also properly change \(
to [(]
since in JS, "foo\(bar\)" === "foo(bar)"
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With