I need to find out at what position in terms of parent > child:eq(n) the current selector sits, so that I can use .insertAfter() and .insertBefore() to properly move the element around within it's nest.
I've looked through several parts of the jQuery doc, but I've yet to find a function that gives the current selector's position within it's parent relevant to nest structure (as oppose to dimensional position when can be found through .postion()).
Any points to the right function for this, or a good way to move around elements in the following structure using jQuery would be greatly, greatly, greatly appreciated ;)!
<ul data-submenu="1" class="sub-menu">
<li>Text Module</li>
<li>Feature Module</li>
<li>Feature Module</li>
</ul>
(I need to move each <li> element around within the <ul> parent).
It seems you're looking for the index() method, which, if provided with no parameters, returns the elements position relative to it's siblings.
var index = $(this).index();
It sounds like you want to use $.each():
$('.sub-menu').children('li').each(function(index) {
console.log('This is the ' + index + ' li element.');
});
Related
So I currently have a list like so on my page
<li class="head">
<b>Introduction</b>
<ul>
<li class="sub">somethingsomething</li>
</ul>
</li>
This list is being used with sortable, so the user can decide on the order, and I am passing this information to a grails controller for use in application logic. So, I am trying to read it in, and place the text contained in the "head" and "sub" classes in 2 different arrays. However, when I use a jquery selector to obtain the head elements, and obtain the text attribute of the element, it contains the inside list as well.
$('#divname').find("ul > li.head").each(function()
{
var current = $(this);
console.log(current.text());
});
results in Introductionsomethingsomething
Is there any way to only obtain the 'Introduction' text from the list, and ignore the text in the nested <ul> and <li.sub>? Due to it being nested, I am unable to figure out how to use jQuery's :not() selector
You can find the b tag using jquery tagname selector.Like this:
var current = $(this).find('b');
console.log(current.text());
Working Demo
May be this is solution:
<script>
$('#divname').find("ul > li.head").each(function()
{
var current = $(this).find("b");
console.log(current.text());
});
</script>
Jquery:
//Jquery-JS search for actors and directors
//Hide extra Actors
$(".actor ul li").not($(".actor ul li").slice(0,11)).hide();
//
function find_and_unhide (keyword,container) {
$(container+':contains("'+keyword+'")').show();
}
find_and_unhide("fra",".actor ul li");
Html:
<div class="option-combo actor">
<h4>Actor →</h4>
<ul class="filter option-set" data-filter-group="actor">
<li>Any</li>
<li>Sandro</li>
<li>Barbara</li>
<li>Ku</li>
<li>Cool</li>
<li>Aid</li>
<li>Leo</li>
<li>John</li>
<li>Kvara</li>
<li>Kuku</li>
<li>Bubu</li>
<li style="display: none;">Fra</li>
</ul>
</div>
Find and Unhide function doesn't work.
I'm also wondering if I should use data-filter-value instead of contains to select correct li. But which one will be faster?
Also How do i implement fuzzy matching?
I would do something like this to fix your find and unhide function:
function find_and_unhide (keyword,container) {
$(container).find('[data-filter-value="' + keyword + '"]').show();
}
I definitely think searching on the data attribute would be both faster and be more extensible in the long term, however, especially since you narrow down the DOM that needs to be searched I imagine the performance difference will be negligible either way. I personally think its cleaner to use the data attribute.
Don't know much about fuzzy matching, but maybe this question will give you a starting point : Getting the closest string match
I made a table out of a simple list structure:
<html>
<body>
<ul id="Column:0">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
<ul id="Column:1">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
<ul id="Column:2">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
</body>
</html>
Now I want to add a simple .mouseover() to every row, for e.g. changing the color of a row, when hovered. And this is what I figured out, so far:
for (var i = 2; i <= _totalRows; i++) {
var row = $('#TimeTable ul li:nth-child(' + i + ')')
row.each(function() {
$(this).click(function(evt) {
var $target = $(evt.target);
console.log($target.nodeName)
if (evt.target.nodeName == 'DIV') {
console.log(evt.parent('li'));
}
}); //end $(this).click(fn)
}); // end each(fn)
}
I get a set of all <li> objects matching to :nth-child(i) where i is the rows number.
var row = $('#TimeTable ul li:nth-child(' + i + ')')
Now I just iter this set through to add a .click(fn) to every <li>.
This works fine. Every cell has it's .click(fn) attached to it.
But the following, what to do on a click, is where I'm stuck for several hours now:
var $target = $(evt.target);
console.log($target.nodeName)
if (evt.target.nodeName == 'DIV') {
console.log(evt.parent('li'));
}
I simply don't get it to run.
You can actually ignore this gibberish, as it's just the last of several things I already tried here.
What I'm trying to do is simply select every <li> with an id='Row:X' and manipulate its CSS. The best I yet had was, that I can click a cell, but no matter in what row this cell is, the last one gets colored. I remember having used i as the row-index, when that happened, so I might miss some understanding of event-handling here, too.
Use a class name for duplicate groups of elements not an ID. If you give row one a class of "Row1" the selector is simply:
$('.Row1')
Then:
$('#TimeTable li').removeClass('highlight');
$('.Row1').addClass('highlight');
If you just wish to change the color on mouseover:
$('#TimeTable ul li').mouseover(function(){
$(this).css('background','red');
});
$('#TimeTable ul li').mouseout(function(){
$(this).css('background','green');
});
Make your ID's like so: C1R1 (Column1Row1) and so on
JQuery read/google up "jquery each"
JQuery read/google up "jquery bind click"
JQuery read/google up "jquery attr" and "JQuery val()"
This will give you the knowledge to write your own and most importantly understand it better. You will want to achieve the following (your close but no for loop required):
A list which JQuery attaches a click event handler to each LI, and then when the click happens the ID can be retrieved.
PS. There's a time and place for tables, they 9/10 times nearly always better for displaying data than CSS is. If you have a complex multi column row and want fiexed hights and no JS to fix things or do anything smart you can have a table and css :Hover on TR for stying mouse over and out etc. Heights are also constant.
PS. PS. If your data is dynamic and coming from a database and the whole row is an ID from the database I tend to avoid using the html ID attribute for this and make my own. You can retrieve this via attr("myattribute");
NOTE ON CSS and IDS:
Standard practice for ID's are to be used once on a page.
Class for repeatable content
Good luck.
I have a guide where each chapter is located in a separate LI of a UL. I am trying to use the jQuery Clone function to search through the parent UL that contains all of these 'chapter' LIs, and return those chapters that contain specific text.
Right now, I'm getting odd results, likely because it's copying elements at their smallest child, rather than just the entire div.
Also, each of these chapter LIs should only be returned once.
makeIntoSldieshowUL - UL that contains all 'chapters'
slideShowSlide - class name for each 'chapter'
searchResultsArea - Div in which to append 'chapters' that contain text
So far I have:
$("#makeIntoSlideshowUL").find(".slideShowSlide:contains('" + $(this).val() + "')").clone().appendTo("#searchResultsArea");
To give you an idea of the content I'm looking to clone, here is a brief sample
<ul id="makeIntoSlideshowUL">
<li class="slideShowSlide" id="0">
<div class="topicTitle">Cardholder responsibilities</div>
<p>Cardholders are responsible for ensuring proper use of the card. If your division or department has approved you for a Pro-Card, you must use the card responsibly in accordance with the following requirements:</p>
<ul>
<li>Purchase items for UCSC business use only</li>
<li>Never lend or share your Pro-Card</li>
<li>Purchase only allowable goods and services</li>
</ul>
</li>
<li class="slideShowSlide" id="1">
<div class="topicTitle"><strong>Restricted and Unallowable Pro-Card Purchases</strong></div>
<p>Some types of purchases are restricted are not allowed with the Pro-Card. Disputes with suppliers are initially handled by the Cardholder if, for example, they don't recognize a transaction on their statement, or the amount doesn't match their receipt. The Cardholder is responsible for contacting the supplier immediately to try to resolve the matter.</p>
</li>
Use jQuery's .children() method instead of .find() since it sounds like the .slideShowSlide elements are immediate children.
$("#makeIntoSlideshowUL").children(".slideShowSlide:contains('" + $(this).val() + "')").clone().appendTo("#searchResultsArea");
Or you could use the > child selector instead.
$("#makeIntoSlideshowUL > .slideShowSlide:contains('" + $(this).val() + "')").clone().appendTo("#searchResultsArea");
EDIT: At one point, you seem to refer to the chapters as divs. If they're a child of the <li> elements, you'll likely need something like:
$("#makeIntoSlideshowUL > li > .slideShowSlide:contains('"...
try using the has or contains selector
has will not change the current element on the jquery stack.
$("#makeIntoSlideshowUL")
.has(".slideShowSlide:contains('" + $(this).val() + "')")
.clone()
.appendTo("#searchResultsArea");
Using JavaScript, how can I dynamically change one of the list-items below from this:
<ul class="tabbernav">
<li class="tabberactive"><a title="All">All</a></li>
<li class=""><a title="One">One</a></li>
<li class=""><a title="Two">Two</a></li>
<li class=""><a title="Three">Three</a></li>
</ul>
to
<ul class="tabbernav">
<li class="tabberactive"><a title="All">All</a></li>
<li class=""><a title="One">One</a></li>
<li class=""><a title="Two">-----------NEW LIST ITEM CHANGED---------</a></li>
<li class=""><a title="Three">Three</a></li>
</ul>
I guess you could use getElementsByTagName inside of the ul to get all your list items inside an array. Then you can just edit the third element in your array, with index number 2.
var lItems = document.getElementsByTagName("ul").getElementsByTagName("li");
lItems[2].innerHTML = "<a title='Two'>----NEW LIST ITEM CHANGED-----</a>";
That will ofcourse get all ul elements on the page, and might lead to some strange results if you have more than two uls in your document. But you get the idea, right? Just ask some more if you don't understand what I'm trying to say.
Okay, the above code doesn't really work properly. I've modified my code a bit, but that also included a change in your HTML, as i presume you'll only have one ul "tabbernav", thus I changed it from class="tabbernav" to id="tabbernav". This is the code to do what you want.
var ul = document.getElementById("tabbernav");
var liArray = ul.getElementsByTagName("li");
for (var i = 0; i < liArray.length; i++) {
if(liArray[i].childNodes[0].title == "Two") {
liArray[i].innerHTML = "Your desired output";
}
}
Hope that helps you some more :)
I also suggest using jQuery, which makes selections like this trivial. In your case, you can use the :eq psuedo-selector to get the second line element:
$('.tabbernav li:eq(1)')
This selects the DOM element which is the second li (indexes start at 0) in an element with the class tabbernav. It returns a jQuery object which you can chain other methods to. Changing the inner HTML is done with .html('Your html here').
This is how you select the third Li element of your Ul list in pure JavaScript.
document.querySelectorAll("li")[2].innerHTML = "vasile";
Replace "Vasile" with your desired text.
var list = document.getElementsByTagName("li");
list[2].innerHTML = "<a title='Two'>------NEW LIST ITEM CHANGED----</a>";
this will work perfect
I know that this question is old but since it's still open, see how I modified the first answer. I feel someone else might need it.
>var lItems = document.getElementsByTagName("ul")[0];
>>var nth = lItems.getElementsByTagName("li")[2];
>>>nth.innerHTML = "<a title='Two'>----NEW LIST ITEM CHANGED-----> </a>";
So that basically solves it up by specifying the position of the lItems in particular to grab and in this case [0]. The code will not work properly if that position is missing because getElementsByTagName(NAME) returns a collection of html elements bearing that NAME specified. So that if you don't specify which among them all, the code fails.
If you like code reuse, see a function you can use for that. You just need to specify the parent element and its position and the childNode position and you get the same thing.
>var nthChild = function(parent, pos, childPos){
>>parent = document.getElementsByTagName(parent)[pos];
>>>return parent.children[childPos];
>>>>};
//used thus:
>nthChild("ul", 0, 2).innerHTML = "<a title='Two'>----NEW LIST ITEM CHANGED-----> </a>
";
How do you identify which <li> is the one you want to modify?
If you're doing it by index you could do something like this I think:
var list = document.getElementById("listid");
list.childNodes[2].innerHtml = "<a title='Two'>-----------NEW LIST ITEM CHANGED---------</a>";
Look into using a Javascript library such as JQuery. That will make your life a lot easier. Then you can do something like this:
$('li a[title=Two]').text('Changed Text Goes Here');
You'll need to check my syntax (not sure about the text() function), but it's easy enough to look up in JQuery's api docs.