views:

359

answers:

1

I'm trying to build a screen that will be a hierarchical list of bookmarks, grouped into categories. The categories can be expanded/contracted to show or hide the bookmarks for that category. Right now I'm just working on the UI and using jquery for the first time (and loving it).

The methodology I'm using is sorta like accordion but more than one section can be opened at the same time, and there can be multiple levels deep (accordion only supports one level). For each category, there's a div with an image of a folder in it that will show or hide the next element in the DOM, which would be the collection of bookmarks (usually a <ul>). eg:

<div class="categoryLine" id="d4">
    <img class="folder"....>
    Fourth Menu Item
</div>
<ul id="u4">
    <li id="l41">

I select the element to close using $(this).parentsUntil('categoryLine').next().toggle(transitionSpeed); where the div around the image the user clicks on has a class of categoryLine, and the thing to show/hide is the element following that div.

The problem is in the most complex (deepest hierarchy) part, some things are being hidden that shouldn't be, and reappearing for unknown reasons.

You can see a "working" example here. I've given the relevant tags IDs and put in a debugging alert to display the ID of the element clicked on and the elements to be opened and closed (view source to see this).

  1. Click on the folder for "Fourth Menu Item" to unhide that category. You should see sub 1, sub 2, and sub 3 appear.
  2. Click on the folder for "Fourth Menu Item sub 1". You should see sub 1 expand, but sub 2 completely disappears, including the category line. This is the mystery I'm trying to solve. Clicking on sub 1 correctly says "Toggling 'u411' from category 'd41'" but when the <ul> u411 disappears, so does all of sub 2 disappears. Likewise, if I click on the folder to expand sub2, sub3 disappears.

I am open to implementing this in a completely different way (again, this is my first jquery experiment). I would also be willing to look at solutions where only one category could be open at a time, as long as it still supported a hierarchy instead of one deep like accordion.

Thanks in advance.

+1  A: 

jQuery describes parentsUntil() as:

Description: Get the ancestors of each element in the current set of matched elements, up to but not including the element matched by the selector.

The important part to note there is that you're not selecting .categoryLine. It seems as though you want to be including it though. Should work if you use closest() instead.

$(this).closest('.categoryLine').next().toggle(transitionSpeed); 

As a side note for future reference. ('categoryLine') is not a selector. Typically, you need to include the ., # or element type, ie div. There are more advanced methods though. You may want to read up on jQuery selectors.

munch
Actualy, no. The category line itself is NOT supposed to disappear, otherwise you couldn't open it again. It's whatever element is after the categoryLine div that's supposed to show and hide, and that might be another div, or a ul.When the page loads, 4 category lines show. Clicking on the folder of a category line opens up the contents of that category (the next element) but the category line always stays visible.
dj_segfault
If you look again at that line, I do have a . (class) there. The reason I used class identifiers instead of IDs is to reduce the burden of setting it up. Having to make up and match IDs between the category line and the content was a lot more work. Also, the example I saw at http://michaeljacobdavis.com/tutorials/statesavingaccordion.html worked this way.
dj_segfault
I agree that using a class is correct. You've set it up the right way. However, your syntax is incorrect. The correct syntax is `parentsUntil('.categoryLine')` the `.` let's jquery know to look for something with that class. With my code the category will not disappear. The `next()` element after the category will disappear, which looks like it would be the `ul`.
munch
Taking the code straight from your page and changing the single line to what I have up there worked. Here's a test page. Pardon the broken images. http://jsbin.com/orice
munch
I see your point, and it was a typo. I know the dot is needed. However, when I take the exact same code and put the dot there, *no* folders open up. the debug alert doesn't work either. It says "Toggling 'null' from category 'null'", so with the dot, it's not finding the parent.See http://thekramers.net/tmp/jqueryproblem/accordionfakeiconwithdot.html which is the same exact code except with the dot in the parentsUntil parameter.When I look at the example you sent the URL for, I don't even see the dialog box, let alone opening windows.
dj_segfault
Munch, I actually found a different way to do it that seems to work perfectly. Instead of using .parentsUntil(), I just use .parent(), since the categoryLine div will always be the parent of the folder image. Eg "$(this).parent().next()" instead of "$(this).parentsUntil(".categoryLine").next()" is working perfectly.I'm going to mark your response as the correct answer, though, because you put some time into it, and did in fact find a bug. I would be curious for your feedback on why fixing the selector actually broke it worse though.
dj_segfault
I don't think it's a bug. `parentsUntil` will select all ancestors if the selector is not there or if it returns nothing, so any ancestor that had a `next()` element was affected. `parent()` is a good solution as well. The important thing is you want to select the nearest `.categoryLine` ancestor and then get the next `ul` to toggle. Glad it's working.
munch