finding index of parent of a certain class - javascript

I have the following HTML:
<div class="Wrapper">
<div class="SomeOtherClass"></div>
<div class="SomeOtherClass"></div>
<div class="MyClass">
<div class="SomeElement" id="test"></div>
<div class="SomeElement"></div>
</div>
<div class="MyClass">
<div class="SomeElement" id="test2"></div>
<div class="SomeElement"></div>
</div>
</div>
And I have the following javascript:
$('.Wrapper').find('.SomeElement').each(function () {
if (SomeCondition) {
var TheElement = $(this);
var TheIndexOfParentClass = TheElement... //HERE
return;
}
});
As you can see, I loop through all the SomeElements and I pick one. Now I want to know the index of the parent's class (here "MyClass"). For instance, if I pick out "test" then the TheIndexOfParentClass should be 0 and if I pick out test2 then TheIndexOfParentClass should be 1. Note that the number of elements of SomeOtherClass can vary; I don't want the actual index of the parent, I want the index of the parent's class relative to all children of the Wrapper element. How do I do this?
Thanks.

I think you want this :
$('.Wrapper').find('.MyClass').each(function(TheIndexOfParentClass) {
$('.SomeElement', this).each(function(){
if (SomeCondition) {
var TheElement = $(this);
each pass to the callback the iteration index and so by decomposing the iteration you can ask jQuery to count for you.

If you want to stick with your flow, You could do this also by passing class to index method,
$('.Wrapper').find('.SomeElement').each(function () {
if (SomeCondition) {
var TheElement = $(this);
var TheIndexOfParentClass = TheElement.parent().index('.MyClass'); //HERE
return;
}
});
What we are avoiding here is double each loop.

Related

Changing attributes with click and querySelector not fully functioning

I've written this to change the background of a div that represents hours on a daily planner. The first instance (onclick) works but the others don't. Do I need to give each .container their own id and their own function?
var changeStatus = document.querySelector("#changeStatus");
var container = document.querySelector(".container");
changeStatus.addEventListener("click", function () {
container.setAttribute("class", "filled");
}
querySelector() is designed to return a single element only. If there are multiple elements matching the .container selector then it will only return the first.
In your case you need to use querySelectorAll() to retrieve all relevant elements, then you need to loop through them to update the class.
var changeStatus = document.querySelector("#changeStatus");
var container = document.querySelectorAll(".container");
changeStatus.addEventListener("click", function () {
container.forEach(el => el.setAttribute("class", "filled"));
});
You can add click listener with loops, something like this:
changeStatus.addEventListener("click", function () {
for(var i=0; i<container.length; i++) {
container[0].setAttribute("class", "filled");
}
}
Here's an example with querySelectorAll as #pilchard answered above:
var changeStatus = document.querySelector("#changeStatus");
var containers = document.querySelectorAll(".container");
changeStatus.addEventListener("click", function () {
containers.forEach(function (container) {
container.setAttribute("class", "filled");
});
});
.filled {
color: #f00;
}
<button id="changeStatus">change status</button>
<div class="container">container 1</div>
<div class="container">container 2</div>
<div class="container">container 3</div>

JS: Selecting a DIV based on its onClick value

I have several different divs with same class, no id and only their onClick function separating them so they are uniquely identifiable, like this:
<div class="nest" onclick="nested.selection('VALUE1'); return false;">
... something inside the div ...
</div>
<div class="nest" onclick="nested.selection('VALUE2'); return false;">
... something inside the div ...
</div>
I would need to find and delete an entire div based on the specified onClick value, but since I cannot use getElementById, Class or Name, how is this lookup achievable with JS (not jQuery)?
try this
document.querySelector('[onclick="nested.selection(\'VALUE2\'); return false;"]').remove()
elements = document.querySelectorAll('.nest');
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', (event) => {
const item = event.target;
item.parentNode.removeChild(item);
});
}
This code will remove div after clicking on it.
Im attaching event handler to all 'nest' elements and then after clicking on specific item removing it.
try this;
var nested = {
selection: function (a, e) {
var element = e.currentTarget;
element.parentNode.removeChild(element);
}
}
html
<div class="nest" onclick="nested.selection('VALUE1',event); return false;">
... something inside the div ...VALUE1
</div>
<div class="nest" onclick="nested.selection('VALUE2',event); return false;">
... something inside the div ...VALUE2
</div>
You don't need to click anything here. Just pass the argument. Like so:
deleteWithArg('VALUE1');
function deleteWithArg(deleteElement) {
var nst = document.getElementsByClassName("nest");
for(var i = 0; i < nst.length; i++)
{
let atr = nst.item(i).getAttribute('onclick').match(/'([^']+)'/)[1];
if (atr == deleteElement) {
nst.item(i).parentNode.removeChild(nst.item(i));
}
}
}
deleteWithArg('VALUE1');
<div class="nest" onclick="nested.selection('VALUE1'); return false;">
... something inside the div with value VALUE1...
</div>
<div class="nest" onclick="nested.selection('VALUE2'); return false;">
... something inside the div with value VALUE2...
</div>

Jquery previous object selector

I have an issue about prev object on jquery it doesnt give me position ...
I have divs with ".post-image"
$(".post-image").each(function(){
var div = $(this);
var index = div.index();
var odd = index % 2;
if(odd == 1){
var sibling = div.next();
sibling.css({
margin:"15px",
marginTop:"-165px"
})
var bElement= div.prev(".post-image");
console.log(bElement)
})
HTML:
<div class="post">
<div class="post-header"></div>
<div class="post-content"></div>
</div>
<div class="post-image">
<div class="post-header"></div>
<div class="post-content"></div>
</div>
I cant select prev as an object
As for the jQuery docs:
.prev( [selector ] ) Get the immediately preceding sibling of each element in the set of matched elements, optionally filtered by a selector.
Reference
Your <div class="post-image"> element has no immediately preceding element with the same class. The element preceding it is <div class="post">
[EDIT]
You can go this way:
// declare bElement variable:
var bElement;
$(".post-image").each(function(){
var div = $(this);
var index = div.index();
var odd = index % 2;
if(odd == 1){
var sibling = div.next();
sibling.css({
margin:"15px",
marginTop:"-165px"
});
// make sure that previous element with class '.post-image' exists :
if(bElement !== undefined){
var prevElemPosition = bElement.position().top;
// do something ...
}
}
// set latest .post-image element (so that it will be the previous on next iteration):
bElement = div;
});

How to find element of div from another div

I have the elements in the div as mentioned below:
<div id="container">
<div id="first_div">
<div id="comment-1" class="comment">Child 1 of first div</div>
<div id="comment-2" class="comment">Child 2 of first div</div>
<div id="comment-3" class="comment">Child 3 of first div</div>
<div id="comment-4" class="comment">Child 4 of first div</div>
</div>
<div id="second_div">
<div id="comment-5" class="comment">Child 1 of second div</div>
<div id="comment-6" class="comment">Child 2 of second div</div>
<div id="comment-7" class="comment">Child 3 of second div</div>
<div id="comment-8" class="comment">Child 4 of second div</div>
</div>
<div id="third_div">
<div id="comment-9" class="comment">Child 1 of third div</div>
<div id="comment-10" class="comment">Child 2 of third div</div>
<div id="comment-11" class="comment">Child 3 of third div</div>
<div id="comment-12" class="comment">Child 4 of third div</div>
</div>
I need to retrieve the next element from comment id comment-4.
$('#comment-4').next().attr('id') gives me result as undefined.I need the target div to be comment id - comment-5.How to retrieve the next element of div from another div using jquery?
Try this :
$(function(){
$('.comment').click(function(index){
var id;
if ( $(this).is(':last-child') )
id = $(this).parent().next().children(':first').attr('id');
else
id = $(this).next().attr('id');
alert(id);
});
});
Demo
Demo : http://jsfiddle.net/abdennour/PU54r/
function nextOf(id,cyclic){
var ids= $('div[id^=comment-]').toArray().map(function(e){return $(e).attr('id')}).sort();
var idx=ids.indexOf("comment-"+id);
if(idx!==-1){
if(ids.length> idx+1){
return $('div#'+ids[idx]);
}
else{
// it is the last div: if it is cyclic ,you may return the first
if(cyclic){
return $('div#'+ids[0]);
}
}
}else{
// no div with this id
}
}
Then :
var target=nextOf(4)
if(target){
target.html()
//--> Child 1 of second div
}
I think you can use $('.comment') to pick up all of your wanted, and save them in some variable such as var arrResult = $('.comment');.
So far, you can choose what you wanted use the arrResult variable.
Because your inner-most divs have different parents, I would first get all the divs you care about:
var comments = $('.comment');
Next, if we can assume your id's are all numbered sequentially, get the number in the id (assuming this references the element):
var index = parseInt($(this).attr('id').substr(8));
Now, the next div in the comment list is at that position in the comments:
var nextDiv = comments[index];
Just for good measure, I'd first make sure index is set:
var nextDiv;
if (index < comments.length) {
nextDiv = comments[index];
}
You could use an index in your case :
JS:
for (var index = 0; index <= 12; ++index) {
$("#comment-" + index).attr("id");
}
You can define a statement which checks the target id is the last child, than you can return a function according to value.
jsFiddle Demo
var target = 'comment-4';
$('.comment').each(function(i) {
if ( $(this).attr('id') == target ) {
if ( $(this).is(':last-child') ) {
$(this).parent().next().children().first().addClass('red');
}else{
$(this).next().addClass('red');
}
}
});
Here is one way - http://jsfiddle.net/jayblanchard/WLeSr/
$('a').click(function() {
var highlight = $('.highlight');
var currentIndex = $('.comment').index(highlight); // get the index of the currently highlighted item
$('.comment').removeClass('highlight');
var nextIndex = currentIndex + 1;
$('.comment').eq(nextIndex).addClass('highlight');
});
It is showing undefined because comment-4 and comment-5 are childrens of different parent elements. Means comment-4 is children of first_div and second_div parent of comment-5.
You can get the comment-5 using below code.
$('#comment-4').parent().next().children().attr('id');
Assuming jQuery-wrapped element is collected in $comment, there's one way to solve it:
function getNextComment($comment) {
var $nextComment = $comment.next();
if ($nextComment.length) {
return $nextComment;
}
var $nextParent = $comment.parent().next();
if ($nextParent.length) {
return $nextParent.children().first();
}
return null;
}
Demo. Click on one comment - and see the next one's highlighted. )
The base algorithm's very simple here. First, we attempt to retrieve the next sibling of the given element. If there's one, it's returned immediately. If not (and it's the case with #comment-4 in your question - it's the last element in its hierarchy), we go up the DOM chain for its parent (#first-div, in this case), and look for its next sibling (#second-div). If it exists, then its very first child element is returned. If it doesn't, null is returned (we can actually return an empty jQuery object - $(), but that depends on use cases.
Just one instruction : )
$('<div id="mock" />').append($('.comment').clone()).find('#comment-4').next().attr('id')//---> comment-5
Based on divs have the same Css class .comment
DEMO
Why not this will be undefined: $('#comment-4').next().attr('id') because there is no next element. as you mentioned that you want to target the #comment-5 in the next div's child then you can do this:
function giveId(el) {
var sel = el.id ? '#'+el.id : '.'+el.className;
var id = $(sel).next('div').length ? $(sel).next('div').attr('id') : $(sel).parent('div').next('div').find('> div:first').attr('id');
return id || "Either no next elem exist or next elem doesnot have any id/class.";
}
$(function () {
$('div').click(function (e) {
e.stopPropagation();
alert(giveId(this));
});
});
Updated Demo in action
Try this: JSFiddle (The easiest solution!)
$(document).ready(function(){
var currDiv = $("#comment-4"); // Try with different valies: "#comment-x"
currDivId = currDiv.prop('id');
lastDivId = currDiv.parent('div').find('.comment').last().prop('id');
if(currDivId == lastDivId){
var nextComment = currDiv.parent('div').next('div').find('.comment').prop('id');
}else{
var nextComment = currDiv.parent('div').find('.comment').next().prop('id');
}
alert(nextComment);
});

Remove parent element after removing last child element

I have a list of elements on a page, for the sake of discussion we can say I have the following:
<div id="group_01">
<div id="entry_1-01">stuff x</div>
<div id="entry_1-02">stuff x</div>
</div>
<div id="group_02">
<div id="entry_2-01">stuff x</div>
<div id="entry_2-02">stuff x</div>
</div>
The delete link calls an Ajax request and deletes the entry, after a succesful Ajax call, the entry div is removed from the page. My question is:
How can I remove the containing group div once all of it's entries have been deleted?
I hope that's a detailed enough question. I feel like this isn't anything new, yet two days of search has resulted in nothing.
Before you delete the child element, get its parent, count the number of children, and then after deleting the child, delete the parent if the child count is zero. Here is a quicky piece of sample code:
function d (x)
{
var e = document.getElementById(x);
var p = e.parentNode;
p.removeChild (e);
if (p.childNodes.length == 0) {
var pp = p.parentNode;
pp.removeChild (p);
}
}
I added onclicks to your divs like this:
<div id="group_01">
<div id="entry_1_01">stuff 11<a onclick="d('entry_1_01');" href="#delete">x</a></div>
<div id="entry_1_02">stuff 12<a onclick="d('entry_1_02');" href="#delete">x</a></div>
</div>
I also changed the link to "#delete". You could tidy this up in various ways.
A function like this should would work:
function removeNodeIfEmpty(node) {
var container = document.getElementById(node);
var nodeCount = 0;
for (i = 0; i < container.childNodes.length, i++) {
if (container.childNodes[i].nodeType == 1) {
nodeCount += 1;
}
}
if (nodeCount < 1) {
container.parentNode.removeChild(node);
}
}
This should account for the whitespace issue.
Assuming you do something like this to remove an entry:
entryDiv.parentNode.removeChild(entryDiv);
then you should be able to use the following code to remove the group div when the last child is removed:
var groupDiv = entryDiv.parentNode;
groupDiv.removeChild(entryDiv);
if (!groupDiv.firstChild) {
groupDiv.parentNode.removeChild(groupDiv);
}
...although you need to watch out for whitespace-only text nodes, if these entries haven't been created directly by script.
Really depends what library you're using
http://docs.jquery.com/Traversing/parent#expr
should be a suitable expression

Categories

Resources