tags:

views:

49

answers:

2

I want to create a rule to match only on the following:

<ul id="root">
   <li>
      <a href="item.html">Root Menu Item</a>
   </li>
</ul>

However it must not match if the "li" element contains another "ul" element:

<ul id="root">
   <li>
      <a href="#">Sub Menu</a>
      <ul>
         <li>
            <a href="item.html">Sub Menu Item</a>
        </li>
      </ul>
   </li>
</ul>

The event for the rule is a click() function on the "a" element, I have created the event as required but need it to only work on the root menu items.

I know I can just add an id attribute to target the desired element only but the menu plugin that my client has installed is not easily configurable.

+2  A: 
$('#root a').click(function(e) {
    if ( $(this).parents('ul').length > 1 ) {
       e.preventDefault(); // cancel action for anchors inside of #root who have multiple parent list elements 
    }
});

Change logic per requirement.

meder
Cheers. Is e.preventDefault(); the same as return false;? Which is faster?
GSTAR
`return false` causes the function to cease. `preventDefault` is the standard DOM method. I would just use the latter, I would think `return false` is "faster" because you exit immediately whereas `preventDefault` still does some things internally.
meder
+4  A: 

If you're matching the a do this:

var result  = $('#root > li:not(:has(ul)) > a');

If you want to allow deeper nested <ul> elements, and just want to check to make sure only the direct children don't have a <ul>, you could do this:

var result  = $('#root > li:not(:has(> ul)) > a');

EDIT:

To have more than one selector at the same time, separate them with a comma inside the quotes:

var result  = $('#root > li:not(:has(> ul)) > a, #someOtherElement');
patrick dw
Cheers, I'm matching on the "a" tag. This has worked perfectly.
GSTAR
How can I do "OR" conditions for my click function, for example if I wanted to have the same click function for another tag?
GSTAR
@GSTAR - Glad it worked. I'm going to give one more update that will allow you to have deeper nested `<ul>` elements if needed.
patrick dw
@GSTAR - You can separate selectors with a comma (inside the quotes). I'll update with an example.
patrick dw
@GSTAR - Just want to make sure of one thing. You don't have more than one `<ul id="root">` do you?
patrick dw
@patrick - no I do not.
GSTAR
By the way what benefit is there of using the > (child selector?) I noticed it still works if you don't put in the child selector.
GSTAR
@GSTAR - I wasn't sure of your entire markup. It is probably not necessary in your case. Say if at the top level you had an `<a>` element that didn't have any `<ul>` siblings, but it did have a `<div>` sibling, and that `<div>` had a `<ul>` descendant, then with the first selector, the `<a>` would not be selected, because `:has()` searches deep into the descendants. So if you wanted that `<a>` to be selected given that scenario, you would use the second example I gave, because the `:has()` would only match `<ul>` elements that are direct descendants of the `<li>`.
patrick dw
@GSTAR - ...consider this example that uses `has(> ul)`: http://jsfiddle.net/wkCvV/ It alerts 1 result, because I wrapped the nested `<ul>` in a `<div>`. Remove the `<div>` tags and click **Run** at the top, and it alerts 0. Or keep the `<div>` but do `has(ul)`, and the result will be 0, when you may want 1.
patrick dw
Patrick, thank you very much! You opened up my world of jQuery selectors greatly.
Emtucifor
@Emtucifor - Glad I could help. :o)
patrick dw