3

I have this table.

<input id="emp_search" />
<input id="search" type="button" value="search" />
<table>
   <tr>
       <th>First Name</th>
       <th>Last Name</th>
       <th>number</th>
       <th>letters</th>
       <th>Gender</th>
       <th>Company</th>
   </tr>
   <tr>
       <td>John</td>
       <td>Lennon</td>
       <td>151</td>
       <td>sf</td>
       <td>Male</td>
       <td>Corp (Technologies)</td>
   </tr>
   <tr>
       <td>Paul</td>
       <td>McCartney</td>
       <td>753</td>
       <td>tj</td>
       <td>Male</td>
       <td>Corp (Services)</td>
   </tr>
   <tr>
       <td>George</td>
       <td>Harrison</td>
       <td>24</td>
       <td>ge</td>
       <td>Female</td>
       <td>Corp Technologies</td>
   </tr>
   <tr>
       <td>Ringo</td>
       <td>Starr</td>
       <td>26</td>
       <td>hg</td>
       <td>Female</td>
       <td>Corp (Help Desk)</td>
   </tr>
</table>

when you search exact words like "John Paul" or "John Mccartney", the result should be 2 rows containing the searched word. (now that's the function of my jquery , that you can find multiple words and result to multiple exact result.

Now my problem is , when you searched the words containing with the parenthesis like "SMS Global (Help Desk)." it doesn't even work.

$(function () {
    $(' #search ').click(function () {

        var str = $('#emp_search').val();
        var strary = str.split(' ');

        $("table").find("tr").slice(1).each(function (index) {
            var text = $.trim($(this).find("td:nth-child(6)").text());

            for (var i = 0; i < strary.length; i++) {
                console.log("%s:%s", text, strary[i]);
                var regex = new RegExp(".*\\b" + strary[i] + "\\b\.*", "gi");
                $(this).toggle(regex.test(text));
                console.log(regex.test(text));
                if (regex.test(text)) 
                    break;
            }
        });
    });
});

ok here's an explanation. let's say that the only column that i could search in is the 1st column. where you could type john and paul , which is in the same column. and exact word. so about the sms global (technologies), i will search the sms global (technologies)|sms global (help desk) and will result to two rows containing the word that is searching.

JSFiddle

is there something wrong with the code? I don't know these code. I just found it. and I'm trying to practice and understand it. But right now I'm just a new programmer.

Vincent
  • 852
  • 6
  • 29
  • 67
  • Are you asking for a regular expression to parse HTML? – Qantas 94 Heavy Dec 02 '13 at 09:28
  • @Qantas94Heavy wait i'll add the jsfiddle i found. – Vincent Dec 02 '13 at 09:29
  • 1
    the second loop can be eliminated.... http://jsfiddle.net/arunpjohny/5kqEt/1/ still the `)` does not work – Arun P Johny Dec 02 '13 at 09:31
  • @ArunPJohny yeah. Interesting right? it doesn't work even it escaped. – Vincent Dec 02 '13 at 09:33
  • 2
    @Vincent yes!!! not a RegEx guy.... so not sure why – Arun P Johny Dec 02 '13 at 09:35
  • same here. i dont know regex.. -_- – Vincent Dec 02 '13 at 09:39
  • 1
    http://stackoverflow.com/a/2593661/1225328 will solve your problem. – sp00m Dec 02 '13 at 10:10
  • Works for me. Searching for "Technologies" in your jsfiddle returns John Lennon – Taemyr Dec 02 '13 at 10:19
  • for now why don't you go with something like http://jsfiddle.net/arunpjohny/5kqEt/3/ the problem with this is if you search for `oh` `john` will return true – Arun P Johny Dec 02 '13 at 11:09
  • @Taemyr try typing the full word sms global (technologies) – Vincent Dec 03 '13 at 01:06
  • "sms global (technologies)" works just fine. It returns all rows, because every row has sms. "(technologies)" returns two hits because the grouping is essentially ignored. "(Help Desk)" Fails becuase it gets split into "(Help" and "Desk)" and thus forms malformed regexp. I have detailed what goes wrong in my recently added reply. – Taemyr Dec 03 '13 at 09:12
  • 1
    @sp00m Just escaping the regexp is not sufficient. `/.*\b\(technologies\)\b.*/` does not match SMS Global (Technologies). – Taemyr Dec 03 '13 at 09:15
  • @Taemyr Is your regex case insensitive? If not, add the `i` flag at the end of your regex: `/regex/i`. – sp00m Dec 03 '13 at 09:22
  • @sp00m I use OP code for my answer, so it is insensitive there. `/.*\b\(technologies\)\b.*/i` should not match SMS Global (Technologies) either. The problem is that there is no word boundary between space and '(' – Taemyr Dec 03 '13 at 09:36
  • @sp00m i need to get only the specific row. which is sms global (technologies) only – Vincent Dec 03 '13 at 09:58
  • 1
    @Vincent Then you need to put on a thinking hat and tell us why "John Paul" should match 2 rows, rather than none, while "sms global (technologies)" should match 1 row, rather than 4. Ie. what makes the first something that should match any of the words while the latter should match the whole phrase. – Taemyr Dec 03 '13 at 10:24
  • @Taemyr oh im sorry. i updated my post. – Vincent Dec 04 '13 at 01:26

2 Answers2

3

This will help you to search with parenthesis

See the Fiddle : CLICK ME

Here is code :

$(function () {


    $(' #search ').click(function () {

        var str = $('#emp_search').val();
        var strary = str.split(' ');

        $("table").find("tr").slice(1).each(function (index) {
            var text = $.trim($(this).text());
            for (var i = 0; i < strary.length; i++) {
                console.log("%s:%s", text, strary[i]);
                var tempStr;
                tempStr = strary[i].replace("(", "\\(");
                tempStr = tempStr.replace(")", "\\)");
                alert(tempStr);
                var regex = new RegExp(".*" + tempStr + ".*", "gi");
                $(this).toggle(regex.test(text));
                console.log(regex.test(text));
                if (regex.test(text)) break;
            }
        });
    });

});

enter image description here

SeeTheC
  • 1,560
  • 12
  • 14
  • This solves the problem for parentheses, but not for other regex special characters. The comment from @sp00m above has a link to a better solution. – r3mainer Dec 02 '13 at 11:10
  • @squeamishossifrage The link doesn't give the full answer, because OP's regexp searches by word boundaries and there is no boundary between space and '('. So just escaping is insufficient. See my reply. – Taemyr Dec 03 '13 at 09:13
1

There is two problems with the paranthesis in your regexp.

The first is that parantheses have special meaning within regexp.

In order to avoid difficulties with special characters you would need to escape these.

The following function is taken from the stackoverflow question How to properly escape characters in regexp

function quote(regex) {
  return regex.replace(/([()[{*+.$^\\|?])/g, '\\$1');
}

You could use it like this

for (var i = 0; i < strary.length; i++) {
   console.log("%s:%s", text, strary[i]);
   var regex = new RegExp(".*\\b" + quote(strary[i]) + "\\b\.*", "gi");
   $(this).toggle(regex.test(text));
   console.log(regex.test(text));
   if (regex.test(text)) break;
}

However this will not resolve your problem.

Because in addition to being a special character '(' is a non-word character. Your regexp searches for a boundary between word and non-word character, followed by the search string, followed by another boundary between word and non-word. Because '(' is a non-word character there is no boundary between a space and '('.

You have several methods to resolve this. One would be to remove non-word characters from the start or end of your search string. Another would be to remove the word boundary if your string start or end with a non-word character. Or replace the word boundary with a word non-boundary if the string starts or ends with a non-word character.

Alt1:

function clean(regex) {
  var tmp=regexp.replace(/^\W|\W$/g, '');
  return "\\b" + tmp.replace(/([()[{*+.$^\\|?])/g, '\\$1') + "\\b";
}

Alt2:

function clean(regex) {
  var tmp=regexp.replace(/([()[{*+.$^\\|?])/g, '\\$1');
  tmp=tmp.replace(/^((\\)?\w)/, '\\b$1')
  tmp=tmp.replace(/((\\)?\w)$/, '$1\\b')
  return tmp
}

Alt3:

function clean(regex) {
  var tmp=regexp.replace(/([()[{*+.$^\\|?])/g, '\\$1');
  tmp = "\\b" + regexp + "\\b"
  tmp = tmp.replace(/^\\b((\\)?\W)/,'\\B$1')
  tmp=tmp.replace(/((\\)?\W)\\b$/, '$1\\B')
  return tmp
}

Use with

for (var i = 0; i < strary.length; i++) {
   console.log("%s:%s", text, strary[i]);
   var regex = new RegExp(clean(strary[i]), "gi");
   $(this).toggle(regex.test(text));
   console.log(regex.test(text));
   if (regex.test(text)) break;
}

CAUTION: the above is not tested and can contain errors.

Community
  • 1
  • 1
Taemyr
  • 3,407
  • 16
  • 26