0

I just asked a question here about selecting all id's of the form id_* where * is any string and id is the id of the element. I got a great working solution:

$("*[id^=" + id + "_]").each(function() {... // id is the element name

I need to take this one step further now: All of my ids will be of the form: a_b_c ... where a b and c are arbitrarity strings (that do NOT contain a ''). So, now rather than selecting all the elems of the form id_* where * could be a_b_c ... I need only to select 1 level deep: i.e. all elems of the form id_a. So in other words it stops at the next ''. Is this possible?

As an example:

If my id is: first And there exist id's: first_second, first_second_third It will select only first_second

6
  • 1
    I think you may want to explore using the "class" value of your elements to identify and select them. Commented Aug 20, 2010 at 14:13
  • Actually. I am using id's. They are all unique so what does it matter? Commented Aug 20, 2010 at 14:15
  • Oh, OK. Well that still seems a little twisted. Maybe you could explain the basic structure and relationship you're trying to represent. The selector pattern matching mechanism isn't really that powerful when compared to an actual regex matcher. You can always do regex matching yourself with a "filter" call, but if you posted your page structure then maybe somebody could suggest an easier alternative. Commented Aug 20, 2010 at 14:17
  • I am representing a tree structure. So a_b_c would mean that the element has a parent a_b, who's parent is a. So for element a (for instance) it would need to find all its direct children (a_x, a_y ..) and not its children's childres. If that makes sense Commented Aug 20, 2010 at 14:19
  • @aeq - If you just want to select direct children, why go through all these hoops with naming the IDs correctly. Why not just use jQuery to only traverse the part of the tree you want? (For example, .children() only get direct children.) Commented Aug 20, 2010 at 14:23

5 Answers 5

1

Sounds like you are storing too many values in the id of the field. With HTML5 we now have data- attributes.

Perhaps, you should be making use of data- attributes something like this to link them?

<div id="a">
</div>

<div id="b0" data-parentId='a'>
</div>

<div id="b1" data-parentId='a'>
</div>

<div id="b2" data-parentId='a'>
</div>

<div id="c" data-parentId='b1'>
</div>

It will still validate, as any non-standard attribute starting with data- will be considered valid.

See: http://ejohn.org/blog/html-5-data-attributes/

Your jQuery selectors can then make use of this new attribute, rather than trying to parse strings

Something like this would select all of a's children

var childrenOfA = $("div[data-parentId='a']);
Sign up to request clarification or add additional context in comments.

Comments

0

What I ended up doing (and I'm open to faster implementations) is:

$("*[id^=" + id + "_]").each(function() {
   //here I simply split the id and test the size of the array
   //if its too large (i.e. too deep in the tree), I return true (to continue
   //  to the next iteration):

   var row = $(this);
   var split = row.attr('id').split("_");

   if(split.length > SOME_PREDETERMINED_VAL)
      return true;

   //code here
});

I am not totally happy with this since it still traverses all elements (or would it do this anyway regardless of the filter in the each() function??).

Comments

0

This doesn't give you the whole solution, but you could try the attribute prefix selector or the attribute starts with selector

That will allow you to select any descendant of an element:

$("[id^='a_b_']").each(....

Will think how to remove the grandchildren etc, but this might get you started.

EDIT

I have just found that a similar question was asked about jQuery wildcards - this looks as if it will do what you need.

Comments

0

It seems like you are seriously overcomplicating this task. Let's say your structure is currently like this:

<div id="a">
    <div id="a_b">
        <div id="a_b_c">
        </div>
    </div>
</div>

Why don't you just do something along these lines...

<div id="a">
    <div class="b">
        <div class="c">
        </div>
    </div>
</div>

So, if I JUST wanted #a .b I would do:

$("#a .b").not("#a .c").show();  

Makes it a bit more semantic and readable as well. Am I understanding what you're trying to do? Might need to shed a bit more light on what exactly you're doing

1 Comment

the problem is in your assumption of my structure (my fault for not elaborating). Like I said in one of my comments, its only a logical table..so it doesn't follow a nice hierarchy (like you showed with the nested divs). Its rather complicated since the tree is within a table structure (specifically the row headers). So while I'm sure it may be regular in some way, using a relative patter would be crazy complicated (much more so than the solution I was getting at with my question).
0

The obvious solution is changing your document, for example instead of

<div id="a"></div>
<div id="a_b"></div>
<div id="a_b_c"></div>

you could write

<div id="a" class="l1"></div>
<div id="a_b" class="l2"></div>
<div id="a_b_c" class="l3"></div>

and then select $('.l2[id^=a_]'). If that is not an option, you could try some sort of sieve scheme:

var set = $('[id^='+id+'_]'), i = 0;
while (i < set.length) {
    var e = set.eq(i);
    if (e.attr('id').substr(id.length+1).match('_')) {
        set = set.not(e);
    } else {
        i++;
    }
    set = set.not($('[id^='+e.attr('id')+'_]'));
}

(I haven't tested, so there might be errors, and I'm not sure not is the one that subtracts from a result set, but you get the idea.)

It depends on the document structure and browser whether this will be actually faster than the naive implmentation of simply walking through the while set and skipping everything with two _ in the id. (High number of branches per node helps, and it will be probably faster on browsers which have a native implementation of the CSS3 prefix selector which jQuery can call on.)

update: fixed some mistakes. The logic might change depending on your structure, e.g. the innermost if branch is unnecessery if foo_bar always precedes foo_bar_baz.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.