Greetings,
I would like to toggle a huge multi-level ul with mootools 1.1 or plain javascript.
The list looks like:
HTML:
<ul>
<li>aaa</li>
<li>bbb</li>
<li>ccc</li>
<li>
<ul>
<li>ddd
<ul>
<li>fff</li>
<li>ggg</li>
</ul>
</li>
<li>eee</li>
</ul>
</li>
</ul>
What I would like to do initially is to show the first level expanded, and the other levels collapsed and when each of the list items is clicked, to expand the ul below it.
Is it possible to do it without (greatly) modifying the html above?
From the documentation, I see that Fx.Slide is the most appropriate, however it accepts the id of the element as a parameter, which means I have to assign id's to each list item.
Is there a way by using selectors of collections of elements starting from the top?
I'm not sure whay I'll say apply with the very old 1.1 version. However, at least since 1.2, the element you need to pass is either the ID (like you said), either the actual element.
If you can use another version than 1.1, try the 1.3 which makes it easier to select the elements you want.
Here, I believe you need every <ul> element which has a direct <li> as parent. MooTools 1.3 features this new selector engine Slick, which would accomplish it fairly easilly: ul !> li.
However, I'm not sure (I didn't success) that the direct child selectors works properly with 1.1.
Here is what I came up with: http://jsfiddle.net/rCfwq/
Related
I have an unordered list, where I am using an ID to identify the current list item that was last clicked. On click of a different item, I am using js to switch the id to a different item in the list, so that styling could be applied.
It seems intuitive to me that a unique item that can only be used once (a selected li item) should be identified as an ID, and that is why I did that, but I was told it is bad practice to do so.
I wouldn't do so. This rather seems an opportunity for you to discover HTML 5's data attribute, which you can use for both CSS styling (using attribute selector) and JS use (with dataset or jQuery's .data() method).
Quick definition from MDN :
HTML5 is designed with extensibility in mind for data that should be
associated with a particular element but need not have any defined
meaning. data-* attributes allow us to store extra information on
standard, semantic HTML elements without other hacks such as
classList, non-standard attributes, extra properties on DOM, or
setUserData.
In HTML side :
<!-- You can use data without value, and just test its presence -->
<li data-selected>
...
</li>
In CSS :
li[data-selected]{
...
}
Your question actually has a couple of interesting components, let me try to answer them as good as I can :-)
"Is it an ok practice to change an ID using javascript if the element is unique?"
You could say it's a justifiable case, if the element really is unique, then there's no real harm in "moving" the ID with JavaScript.
BUT
In your description you touch on something more fundamental:
"On click of a different item, I am using js to switch the id to a different item in the list, so that styling could be applied."
If this is the case (you change the ID for styling), then I'd recommend using a class instead. People previously already gave you a good hint, something like an "is-active" class would be very useful as it's less specfic than an ID, can be used on multiple items if needed and if you use classes that determine a state (like "is-active", "has-children", "is-animating", etc.), it's really easy to re-use them in later parts of code as well and it is clear what the element is doing at the moment.
A little code for reference:
HTML
<ul>
<li>Some item</li>
<li class="is-active">Some item</li>
<li>Some item</li>
<li>Some item</li>
</ul>
CSS
.is-active {
color: #eee;
background-color: #222;
}
jQuery
// You probably want a bit more specific selector, but it's just an example.
$('li').on('click', function() {
var $element = $(this),
$elements = $('li');
if (!$element.hasClass('is-active')) {
$elements.removeClass('is-active');
$element.addClass('is-active');
}
});
Since you might need to reference the specific id of an element at some future point, changing it is probably a bad idea. In your case it would be better to just apply a class to the last item clicked.
I have some <li> elements, like this:
<ul class="some_class">
<li></li>
<li></li>
...
<li></li>
</ul>
And in my css file I have:
.some_class > li
I want to change some of that li elements by jQuery. My idea is to have something like this:
<ul class="some_class">
<div id="some_id">
<li></li>
<li></li>
</div>
...
<li></li>
</ul>
And change its by $("#some_id").html(). But its fails, because of css. I don't want to change css, cause its template css, and it's become very difficult to make changes in it.
Is there some other methods to perfom this?
Given the two pieces of source code you provided, your problem is not the CSS per say, but the way you changed the DOM, making the CSS invalid:
Solution 1:
Change:
.some_class > li
To:
.some_class li
Because in your code manipulation your <li></li> are now direct descendants of some_class your CSS is broken. In CSS > means direct descendant.
Solution 2:
If you don't want to change the CSS just add a class to the <li> you want to change, but do not nest them inside another div.
Note: given the comments about invalid HTML: Solution 2 will not cause a problem with your HTML, and for solution one, replace DIV for another UL
There are lots of ways to target elements, and especially with jQuery this is a breeze.
Of course you can just add a class to each of the elements you want to target, but there are lots of ways to do it without changing your markup at all. For example, you can select using the actual index of the element within the parent using eq(); use pseudo classes like first-child, last-child; use jQuery extensions like :even or :odd; use nth-child to select repeatable patterns like every third element (nth-child:(3n+3))...
For the sake of simplicity I'll narrow down the question as below. I have a large code running in the click js functions. To represent that All I have added an alert()
HTML
<ul>
<li>Test li 1</li>
<li>Test li 2</li>
<li>Test li 3</li>
<li>Test li 4</li>
<li>Test li 5</li>
</ul>
JS
Method 1
$('ul li').click(function(){alert('hi');});
Method 2
$('ul').children().click(function(){alert('hi');});
Method 1 and method 2 both works fine.
Which one is better ? Is it better to use the selector or use the children method ? What's the purpose of having a children method when we can use selector?
Test Fiddle
I'm just grabbing the basics and hope not knowing something is not a crime. Thanks
While both of those pieces of code work correctly on the sample HTML they are not identical.
.children returns all child elements (whether they are an "li" or not).
"ul li" as a selector returns all "li" descendants of the "ul" whether they are children or not.
These two are equivalent and select only "li" children of the "ul" parent:
$('ul > li').click(function(){alert('hi');});
$('ul').children("li").click(function(){alert('hi');});
As for which is better (the original question), there is no real answer for this I suspect and will depend on your actual requirements and html (when you ask for which is 'better' what do you mean? Performance? Maintainability?).
Usually the former will use the CSS selector engine of the browser where the selector you are using is supported, and the later will always use jquery built code (I think) so I would go for the former in most cases.
as to
Which one is better ?..
updated
actually, it depends on the HTML structure... if incase, you have small number of <li>'s in ul (first level) going with children selector is better
you can check this in js.perf...link here
but if you have large number of <li> (in first level) the children selector gets slower ..
I have two examples on jsFiddle:
http://jsfiddle.net/9uhfX/1/
http://jsfiddle.net/9uhfX/2/
Example 1
In the first one I can move the list elements around, even from a child element to the root element. However, it's not very easy to make it "snap".
Example 2
In the second example I have floated the list elements. This time I can't get them to "snap" to the child elements.
Questions
Is there a good way to make it easier to snap?
How do I solve it with float?
There is a so far undocumented option in jQuery sortable to define the element against which tolerance is checked: toleranceElement. If not set, the whole item is checked for placement (including the nested list), but if it's set, only sub-items matching the selector are taken into account.
This means you have to change your HTML markup a bit to wrap the main content of the list item (the item text in your case) in an element and use that to check for sort positioning. That will leave out the nested <ul>s, effectively stopping jittering which is otherwise quite serious.
HTML:
<div id="example5">
<ul>
<li ><div>Item 1</div>
<ul>
<li ><div>Item 1 1</div><ul></ul></li>
<li ><div>Item 1 2</div><ul></ul></li>
<li ><div>Item 1 3</div><ul></ul></li>
</ul>
</li>
<li ><div>Item 2</div><ul></ul></li>
<li ><div>Item 3</div><ul></ul></li>
<li ><div>Item 4</div><ul></ul></li>
</ul>
</div>
Javascript:
$("#example5 ul").sortable({
connectWith: "#example5 ul",
placeholder: "ui-state-highlight",
toleranceElement: 'div'
});
Try your modified demos here and here.
You might also want to play with opacity, cursorAt and tolerance. Have a look at the documentation.
Note that it's not a perfect solution, in case you're not satisfied with the results, have a look at using a plugin. Manuele J Sarfatti's nestedSortable plugin looks like something that might be of use for you: http://mjsarfatti.com/sandbox/nestedSortable/
I'm looking at both of your examples in Safari and I am able to move any element in/out of the children elements without a huge problem.
Here is why #2 is more difficult to use...
The "drop zone" in example #2 is only as high as your element so with your short elements, there is a much smaller area to get your mouse into.
The "drop zone" in example #1 is very wide so it's very easy to hit it as you move your mouse up/down the list.
The only way I can think of to solve your problem is to simply make your items in example #2 taller, thereby simulating what you have in example #1 except on its side.
http://jsfiddle.net/9uhfX/3/
Trying to select span within the first item in a usorted list but I can't quite seem to get the DOM right
<li class="chapterItem"> <a
href="http://www.neuromanga.com/mangaReader.php?chapterNo=12&#pageNo=1"
title="http://www.neuromanga.com/mangaReader.php?chapterNo=12&#pageNo=1
">Naruto 522 world</a> <span
id="date">Nov 21st 2010</span> <br>
<span style="display:none"
class="hiddenChapNo">12</span> </li>
Here is the jQuery code I been trying to use to select it
alert($('li').first().$('.hiddenChapNo').text());
You need to use .find() to get a descendant here, like this:
alert($('li').first().find('.hiddenChapNo').text());
Or a bit more compact with :first and a descendant selector (space):
alert($('li:first .hiddenChapNo').text());
Your code certainly looks like it should work, I assume that there's another <li> before this one that trips it up.
Also, ids are (should be) unique in a web page, so $('#hiddenChapNo') should be sufficient.
Assuming you need multiple hidden spans, the proper way to mark them would be <span class="hiddenChapNo"> (you can then also hide them with CSS instead of inline styles).
Try just using alert($('#hiddenChapNo').text());. An id should be unique on a page, use classes if you need otherwise.
Found a solution
alert($('.hiddenChapNo').first().text());