2

I have tags in a html list, here is an example of two tags.

<div class="tags">
    <ul>
        <li>
            <a onclick="tag_search('tag1');" href="#">tag1
                <span class="num-active">1</span></a>
        </li>
        <li>
            <a onclick="tag_search('tag2');" href="#">tag2
                <span class="num-active">1</span></a>
        </li>
    </ul>
</div>

I would like to write a function that I can pass a string to, that will match the strings in the a hyperlink i.e. "tag1" or "tag2", if there is a match then increment the number in the span, if not then add a new li.

The bit I am having trouble with is how do I search for a string in the div with class tags and then when I find a match identifying the element. I can't even do the first bit as I am use to using an ID or a Class.

I appreciate any help on this using JQuery

Thanks all

Code so far

function change_tag_count(item){

    alert(item);//alerts the string test

    $.fn.searchString = function(str) {
        return this.filter('*:contains("' + item + '")');
    };

    if($('body').searchString(item).length){

        var n = $('a').searchString(item).children().text();

        n = parseInt(n) + 1; 

        $('a').searchString(item).children().text(n);

    }else{
        alert('here');//does not alert this when no li contains the word test
        $("#all_tags ul").append('<a onclick="tag_search(\''+item+'\');" href="#">'+item+'<span class="num-active">1</span></a>');    

    }

}
Abs
  • 56,052
  • 101
  • 275
  • 409
  • When you say "search for a string in the div with class tags" do you mean make a class that you then use as your search term? Or do you want to search the string contained INSIDE the div tags? It would also help to know what the overall objective is, I have a feeling you could be accomplishing your goal in a much easier way. – Trafalmadorian May 19 '10 at 20:59
  • http://stackoverflow.com/questions/926580/find-text-string-using-jquery – brian brinley May 17 '10 at 18:30

4 Answers4

1

The solution you have so far is very inefficient. You might have more luck using an object to keep track of the tags so far, like so:

var tags = {}; // This will memoize the tags we already have
function tagSearch(text) {
  var $match;
  if (tags.hasOwnProperty(text)) {
    $match = tags[text]; // use the one we stored earlier
  } else {
    $match = $([
      '<li><a href="#" onclick="tagSearch(\'', text, '\'); return false;">',
      text, ' <span class="num-active">0</span></a></li>'
    ].join('')).appendTo($('#all_tags ul'));
    tags[text] = $match; // hold onto this for next time
  }

  var $countSpan = $match.find('span.num-active');
  var count = parseInt($countSpan.text(), 10) + 1;
  $countSpan.text(count);
}

I am not sure what your eventual goal is with this code. Depending on what you want to do with it, there are probably much more elegant ways to write this code that would allow you to avoid having to stash onclicks on elements themselves, but I stuck to the way you were already writing it for now.

I did test this code, and it appears to be working, given my understanding of your requirements.

Kent
  • 449
  • 2
  • 5
  • I get this error for some reason: `$match.find is not a function`? It seems to work well except at the point where it has to add a 1 to an existing tag. – Abs May 20 '10 at 22:49
  • It sounds like you either are not storing the newly created $match in tags properly, or perhaps you are not successfully getting the value out of the tags object. Would it be possible for you to post your version of the code? – Kent May 21 '10 at 02:15
0

I didn't test this code but it should work. I would recommend making it easier on your browser and giving each li and ID to avoid the $.each() as you could accomplish the same thing simply with a $("#item").length

function tagSearch(item) {
    $(".tags").find("li").each(function() {
        if($(this).find("a").text() == item) {
            var n = $(this).find("span").text();
            n = parseInt(n) + 1;
            $(this).find("span").text(n);
        } else {
            $(this).parent().append('<li>some html stuff</li>');
        }
    });
}
0

Just use the jQuery :contains selector:

var $matchingElements = $('*:contains("Foo")');

Here’s a quick plugin that does what you want:

$.fn.searchString = function(str) {
 return this.filter('*:contains("' + str + '")');
};

Use it as follows:

// Return all `a` elements in the DOM containing the string 'Foo' as a chainable jQuery object
$('a').searchString('Foo');
// E.g.
$('a').searchString('Foo').addClass('highlight');
Mathias Bynens
  • 144,855
  • 52
  • 216
  • 248
  • What does this `return this.filter('*:contains("' + str + '")');` return if it doesn't find a match? I tried sticking it in a if condition but it didn't get to the else block when it didn't find anything. – Abs May 17 '10 at 19:10
  • If no match is found, it will return an empty jQuery object. (jQuery does the same for every selector that doesn’t match any elements.) You can check for that using `.length`: `var $matches = $('a').searchString('foo'); if ($matches.length) { /* match found */ } else { /* no matches found */ };` – Mathias Bynens May 17 '10 at 19:17
  • I am guessing I should remove the `$` sign as its not php. :) I tried but it still doesn't execute the else block. I have tried `if (matches.length > 0)` as well but the same result. – Abs May 17 '10 at 19:21
  • @Abs: Nope, you can prefix your JavaScript variables with `$` just fine. I like to do so, to make it clear it’s a jQuery object. And what I described should work: `if ($('body').searchString('this string will not be found').length) { alert('match'); } else { alert('no match'); };` alerts “no match”. See http://jsfiddle.net/mathias/Gyanx/ – Mathias Bynens May 17 '10 at 19:28
  • Ah I see, I didn't know. I have changed the if to this`if($('body').searchString(item).length){` and all I am doing now is alerting in the else block but nothing still. What else could I be doing wrong?! – Abs May 17 '10 at 19:36
  • @Abs: It's really hard to help you without you posting your code. What does the variable `item` contain at that point? – Mathias Bynens May 17 '10 at 19:55
  • @Mathis - I have updated my question with code, thank you for your continued help, I really appreciate it! – Abs May 17 '10 at 20:01
  • Maybe you want to do `if($('body').searchString(item).length > 0)` – Daniel Beardsley May 17 '10 at 23:21
  • @Daniel: That is not the issue. `if ($('body').searchString('foo').length)` will either return `0` which evaluates to `false`, or a higher number, which evaluates to `true`. There’s no need to check for `> 0`. – Mathias Bynens May 19 '10 at 05:22
0

Here's what I'm thinking. First off, change the div's class to an ID. Then:

<script language="javascript" type="text/javascript">
function tagSearch(tagToFind){
    var found=0;
    $("#tags>ul>li").each(function(index){
    if ($(this).children("a").html().indexOf(tagToFind)!=-1 && !found)
    { 
        var spanNum=parseInt($(this).find("span").html());
        $(this).find("span").html((spanNum+1));
        found=1;
    }
    else if (index==$("#tags>ul>li").last().index() && !found)
    {
        $("#tags>ul").append('<li><a href="#">tag'+(index+1)
              +' <span class="num-active">1</span></a></li>');
    }
});
}

</script>
</head>
<body>
<div id="tags">
    <ul>
        <li>
            <a onclick="tagSearch('tag1');" href="#">tag1
                <span class="num-active">1</span></a>
        </li>
        <li>
            <a onclick="tagSearch('tag2');" href="#">tag2
                <span class="num-active">1</span></a>
        </li>
    </ul>
</div>
</body>

Then I'd set up your event structure to automatically perform this action if you click on one of those links. The part I don't understand is how you'd have an li that DIDN'T get matched...

Trafalmadorian
  • 2,498
  • 2
  • 21
  • 13