22

I have an object (in this case a rating object from js-kit) that I want to make invisible if the rating value is 'unrated'. I'm having trouble with getting the right jQuery selector to do this.

Even though the code below seems like it should work, it does not.

$(".js-rating-labelText:contains('unrated')").css("visibility", "hidden");  

.js-rating-labelText is a class that's set on the text.

Keavon
  • 6,837
  • 9
  • 51
  • 79
  • 4
    Can you paste the HTML you are running this against? – Paolo Bergantino May 01 '09 at 22:01
  • Its a little complicated (for me at least) as the contents of the ratings div are being filled in by a js-kit javascript function and so are not available at design time. The div is empty (to start) and looks like this:
    –  May 01 '09 at 22:20
  • Strangely, changing the jquery function to add a second parenthesis -- which just looks wrong as it has no matching open paren... $("#ratingDiv:contains('unrated'))").css("visibility", "hidden"); ...causes the first item in the list to be rendered invisible. –  May 01 '09 at 22:22
  • Here is more code:
      <% foreach (var item in Model.Companies) { %>
    • <% } %>
    and script...
    –  May 01 '09 at 22:25
  • I've tried the selector on both the id (#ratingDiv) && the class (.js-rating-labelText) with the same result. –  May 01 '09 at 22:27
  • In this case there are two items (one of which is 'unrated'). The below function makes both sets of text dissapear, regardless of the actual text value: $(".js-rating-labelText:contains('unrated'))").css("visibility", "hidden"); Whereas, the below function renders only the first item invisible, which happens not to be the one that is 'unrated'. $("#ratingDiv:contains('unrated'))").css("visibility", "hidden"); –  May 01 '09 at 22:42
  • You could run a regex on the contents, using innerhtml or .html. It'd be a similar way of finding if it contains a certain string. – Gordon Gustafson May 01 '09 at 22:06

9 Answers9

22

You can create your own selector methods

For example, if you want to be able to do the following:

$('.js-rating-label:hasText(unrated)');

You can define the hasText method as follows

$.expr[':']['hasText'] = function(node, index, props){
  return node.innerText.contains(props[3]);
}

props[3] contains the text inside the brackets after ':hasText'.

tgmdbm
  • 1,553
  • 12
  • 19
  • 2
    This is an excellent answer. I had to change the return function to: return node.innerText.indexOf(props[3]) > -1; – mrmillsy Oct 15 '14 at 10:56
19

Is there another way to select an element based on the text contents?

Try this:

$('.js-rating-labelText').filter(function(){
  return (/unrated/i).test($(this).text())
}).css('visibility', 'hidden');
brianpeiris
  • 10,735
  • 1
  • 31
  • 44
  • Yeah! I set the value based on the class of the parent and used the .hide() method but this worked for me. Thank you so much! $('.js-kit-rating').filter(function() { return (/Unrated/i).test($(this).text()) }).hide(); –  May 01 '09 at 23:33
8

Perhaps the issues is with the :contains('Unrated') part of the function. As changing the text to any random value produces the same result:

$("#ratingDiv:contains('somerandomtext')").hide();
Liam
  • 27,717
  • 28
  • 128
  • 190
  • Is there another way to select an element based on the text contents? –  May 01 '09 at 23:13
  • should it be `$("#ratingDiv:contains('somerandomtext')").hide();` without the closing parenthesis inside? – muyueh Feb 24 '15 at 04:39
1

A slight variant on @tgmdbm's excellent answer. The only difference being that it only selects nodes that have a single child text node exactly matching the hasText() argument. Whereas .innerText returns the concatenation of all descendant text nodes.

  if( ! $.expr[':']['hasText'] ) {
     $.expr[':']['hasText'] = function( node, index, props ) {
       var retVal = false;
       // Verify single text child node with matching text
       if( node.nodeType == 1 && node.childNodes.length == 1 ) {
         var childNode = node.childNodes[0];
         retVal = childNode.nodeType == 3 && childNode.nodeValue === props[3];
       }
       return retVal;
     };
  }
wbdarby
  • 1,129
  • 12
  • 12
0

The best way to explain the topic is by giving an example and a reference link:-

Example:- The following jQuery selector syntax selects the first or nth element from the set of already selected (matched) HTML elements.

$("selector:contains(searchText)")

Html:-

<table>
<tr><td>John Smith</td><td>Marketing</td></tr>
<tr><td>Jane Smith</td><td>Sales</td></tr>
<tr><td>Mike Jordon</td><td>Technology</td></tr>
<tr><td>Mary Jones</td><td>Customer Support</td></tr>
</table>
Search: <input id="txtSearch" type="text">
<input id="btnTestIt" type="button" value="Test It">
<input id="btnReset" type="reset" value="Reset">

Jquery:-

$(document).ready( function(){
    $("#btnTestIt").click( function(){
        var searchText = $("#txtSearch").val();
        $("td:contains('" + searchText + "')").css("background-color", "yellow");
    });
    $("#btnReset").click( function(){
        $("td").css("background-color", "white");
    });
});
Liam
  • 27,717
  • 28
  • 128
  • 190
0

Make sure your code is running after the js-kit function has populated the text, and not before it.

Peter Boughton
  • 110,170
  • 32
  • 120
  • 176
0

You might consider using the hide() / show() methods as well.

$(".js-rating-labelText:contains('unrated')").hide()
Irvin Dominin
  • 30,819
  • 9
  • 77
  • 111
Chris Brandsma
  • 11,666
  • 5
  • 47
  • 58
  • $(".js-rating-labelText:contains('Unrated'))").hide(); Makes both rated and unrated text dissapear. –  May 01 '09 at 23:04
0

Based on the HTML you provided,I don't see where the 'unrated' text you're testing for is coming from.

However, if that is the entirety of the text in that div, just test for it directly.

if ($('.js-rating-labelText').text() == 'unrated'){
  $(this).hide();
}
b. e. hollenbeck
  • 6,493
  • 7
  • 32
  • 47
-1

Here is some of the html coming from the javascript function:

<div class="js-kit-rating" id="ratingDiv" style="width: 86px; visibility: hidden;" jk$initialized="true" path="/business/blogger-com" permalink="/businessblogger-com" freeze="yes" starcolor="Golden">
  <table class="js-ratings-tableWrapper" border="0" cellSpacing="0" cellPadding="0">
    <tbody>
      <tr>
        <td>
          <div class="js-ratingWrapper" style="width: 80px;">
          <div style="float: left; cssfloat: left;">
              <div style="width: 80px; height: 15px;">
<div class=" js-kit-objIcon" style="width: 16px; float: left; height: 15px; cssfloat: left;" imageURL="//js-kit.com/images/stars/golden.png">
  <img style="display: none;" src="//js-kit.com/images/stars/golden.png" complete="complete"/>
<div class=" js-kit-objIcon" style="width: 16px; float: left; height: 15px; cssfloat: left;" imageURL="//js-kit.com/images/stars/golden.png"/>
<div class=" js-kit-objIcon" style="width: 16px; float: left; height: 15px; cssfloat: left;" imageURL="//js-kit.com/images/stars/golden.png"/>
<div class=" js-kit-objIcon" style="width: 16px; float: left; height: 15px; cssfloat: left;" imageURL="//js-kit.com/images/stars/gray.png">
  <img style="display: none;" src="//js-kit.com/images/stars/gray.png" complete="complete"/>
<div class=" js-kit-objIcon" style="width: 16px; float: left; height: 15px; cssfloat: left;" imageURL="//js-kit.com/images/stars/gray.png"/>
<div class=" js-rating-labelText">
  • From what you've told us so far, I see no reason why it shouldn't work. It would be very helpful, if you're up to it, to duplicate the problem on a publicly available host (e.g. jsbin.com). – brianpeiris May 01 '09 at 22:53