Detect length div after append - javascript

I'm having trouble detecting length and index of the appended div, I dug through a lot of things, and there's a solution with MutationObservers but somehow I'm continuously asking myself do I need it for this kind of problem,
However, let's get to the issue. I have a div populated dynamically structured like this,
<div class="array-placeholder">
<div id="tagContainer" class="row tag">
<!-- dynamic elements -->.....
</div>
</div>
when I click to this button it appends another dynamic element, see the code below :
$('body').off('click.addCollection').on('click.addCollection', function () {
//list and new widgets are just containers and datalist inside the array-placeholder div
let newElem = $(list.attr('data-widget-tags')).html(newWidget);
newElem.appendTo(list);
})
I've tried this solution to get the length of the array-placeholder div but it doesn't seem to work, the function is never launched:
$('body').on('DOMSubtreeModified', '.array-placeholder', function (event) {
console.log( $(".array-placeholder > div").length);
})
result
//nothing and when you click to the appended element via moveUpButton.closest(".tag") you 0 as index
do I have to implement MutationObserver to solve this if yes, could you guide me through this, thanks

DOMSubtreeModified
This event has been deprecated in favor of the Mutation Observer API
Yes you have to use Mutation Observer API. To implement that you can refer This

You can get all children using jquery's find('*') and then count their length;
$(".array-placeholder").find('*').length;
Or if you want only divs then do:
$(".array-placeholder").find('div').length;

Related

Select every element that isn't a parent to any elements

I am developing a game that glitches at some point through using the CSS filter: invert(1); property. However, when you use that property on body, it makes everything position: absolute;. This is not good because I need most elements to be fixed, and everything goes to a negative top and not visible. How can I effectively get all elements in a list that isn't a parent to any other elements, but included if it has text? Any answers or other stack overflow topics would be nice!
Here is some of my code:
// In a working loop called Repeat()
if(Glitch == 1) {
document.querySelector(".ChangableStyles").innerHTML = "* {filter: invert(1)}"
} else {
document.querySelector(".ChangableStyles").innerHTML = ""
}
Edit: Since all of you are asking, the .ChangableStyles tag is a style element. The filter on everything applies when I change the innerHTML of that style tag to valid CSS styles. I don't want to be rude, but I have the .ChangableStyles thing figured out. Thank you.
You mention you already have a list of elements, but it's not clear how you're generating that list. I've gone ahead on the assumption you're wanting to "select" all elements in <body></body> that don't have any children.
You can use a combination of Array.from(), your pre-existing selection logic, and a filter() using node.childElementCount === 0 to accomplish what you describe. However on higher-complexity DOMs this will be computationally expensive, so I would implore you to re-consider your design instead of opting for this route. To be clear, this will meet your requirement of selecting ANY Node in the DOM which has no child elements ("isn't a parent to any other elements"), which includes any script, style or other "user-invisible" nodes in the body.
document.getElementById('get-elements-button').addEventListener('click', function () {
console.log(Array.from(document.body.getElementsByTagName("*")).filter(function (node) {
return node.childElementCount === 0;
}));
});
<div class="has-child-elements">
This is a child element
</div>
<div class="has-no-child-elements">
</div>
<div class="has-child-elements">
This is also a child element
</div>
<button id='get-elements-button'>Get elements with child elements →</button>

Get data of specific node element on click

I'm trying to get specific data depending on which node element the user is clicking. I have 4 elements that I have targeted using the querySelectorAll code. What I want to accomplish is that if I click the first element I will console.log that specific data, and if I select the third element I will get that data logged. I've tried a couple of things, but haven't got it to work yet.
function selectedSplit() {
var macroSplits = document.querySelectorAll(".card");
console.log(macroSplits[0].childNodes[3].childNodes[1].innerHTML);
}
It's unclear where you are using selectedSplit - Wether or not it is being used as the event listener return function. But using an onClick event listener, you're return function will be passed the information you need.
If you want to accomplish this in the markup, you could do -
<div class='card' onClick="selectedSplit"></div>
Then you can simply access it via event.target
function selectedSplit(event) {
var thisCard=event.target;
console.log(thisCard.innerHTML);
}
event.target has the clicked element:
d.onclick = e => console.log(e.target)
<div id=d>
<button><b>b</b></button>
<button><i>i</i></button>
<button><u>u</u></button>
<button><s>s</s></button>
</div>

JQuery how to find the closest element that is neither a parent nor a child of the current element?

Say I have HTML that looks like this:
<div>
<div>
<div class="calendar start">
</div>
</div>
<div>
<div class="calendar end">
</div>
</div>
</div>
We can assume that the start and end will always be on the same "level" of a branch from each other, and will at some point share a common parent.
Without knowledge of the exact HTML structure, how would I find calendar end from calendar start? What if they are nested further down?
Edit: For clarification. I want to start at start's parent. Search all child elements for end. Then move to the next parent, and search all child elements...etc till I find end. I am wondering if this is possible with built in JQuery functions, without writing my own DOM traversal logic.
You can do it like below, But it is a costlier process.
var parentWhichHasCalEnd =
$($(".calendar.start").parents()
.get().find(itm => $(itm).find(".calendar.end").length));
var calEnd = $(".calendar.end", parentWhichHasCalEnd);
DEMO
Explanation: We are selecting the .start element first, then we are retrieving its parent elements. After that we are converting that jquery object collection to an array of elements by using .get(). So that we could use .find(), an array function over it. Now inside of the callBack of find we are checking for .end over each parent element of .start, if a parent has .end then we would return that parent. Thats all.
You could get more understanding, if you read .get(), .find(), and arrow functions.
You can use jQuery#next() method from .start parent element
var startSelector = $('body > div > div:nth-child(3) > .start')
var endSelector = secondStart.parent().next().find('.end');
I think this method is faster rather than jQuery#children() method, but you can benchmark it if you want to
btw you may check my answer based on this JSBin
i don't know if i got this right but have you tried children function in jquery
$( ".calender" ).children( ".end" )
and for the parent you can use parent() function so you can first check the parent then the children or vicversa
edit:
if you dont know the exact structure the better way is to find the common parent and then search it's children :
$( ".calender.start").closest('.common-parent').children('.calender.end');
closest function give the nearest parent
Try:
$('.start').parent().parent().find('.end');

Create unique buttons dynamically

I'm new to jQuery and am trying to create jQuery UI buttons dynamically and them to a list. I can create one list item but no more are appended after it. What am I doing wrong?
$('#buttonList').append('<li><button>'+ username + '</button>')
.button()
.data('type', userType)
.click(function(e) { alert($(this).data('type')); })
.append('<button>Edit</button></li>');
<div>
<ul id="buttonList">
</ul>
</div>
This only creates one list item with two buttons (although the second button seems to be encased in the first one, but I can probably figure that issue out). How do I get it to create multiple list items with their own unique 'data' values (i.e. I can't do a find() on a particular button class and give it data values as all buttons would then have the same data)?
I suggest to exchange the position of what you are appending and where you are appending to. This way, you retain the appended object, and should be able to work with it as a standard jQuery selector. From your code i commented out the .button() and the .append() lines, because i'm not sure what you want to do with them. Should you need help adding those lines, just drop a comment to my answer ;)
Oh, i almost forgot: i use var i to simulate different contents for username and userType data.
A JSFiddle for you is here: http://jsfiddle.net/cRjh9/1/
Example code (html part):
<div>
<p id="addButton">add button</p>
<ul id="buttonList">
</ul>
</div>
Example code (js part):
var i = 0;
$('#addButton').on('click', function()
{
$('<li><button class="itemButton">'+ 'username' + i + '</button></li>').appendTo('#buttonList')
//.button()
.find('.itemButton')
.data('type', 'userType'+i)
.click(function(e) { alert($(this).data('type'));
})
//.append('<button>Edit</button></li>')
;
i++;
});
You need complete tags when you wrap any html in a method argument. You can't treat the DOM like a text editor and append a start tag, append some more tags and then append the end tag.
Anything insterted into the DOM has to be complete and valid html.
You are also not understanding the context of what is returned from append(). It is not the element(s) within the arguments it is the element collection you are appending to. You are calling button() on the whole <UL>.
I suggest you get a better understanding of jQuery before trying to chain so many methods together
Just a very simplistic approach that you can modify - FIDDLE.
I haven't added the data attributes, nor the click function (I'm not really sure I like the
inline "click" functions - I generally do them in jQuery and try to figure out how to make
the code efficient. Probably not very rational, but I'm often so).
JS
var names = ['Washington', 'Adams', 'Jefferson', 'Lincoln', 'Roosevelt'];
for( r=0; r < names.length; r++ )
{
$('#buttonList').append('<li><button>'+ names[r] + '</button></li>');
}
$('#buttonList').append('<li><button>Edit</button></li>');

JavaScript equivalent to JQuery .next()

Is there a JavaScript method similar to jQuery .next()? I want to find the next element that has the class of "error" relative to the element. I've tried using .nextSibling as a loop but couldn't figure it out. Didn't know if there was an easier way to go about it without jQuery.
For instance, if I have this code:
<div id="section">
<div id="test">test</div>
<span class="info">Information</span>
<span class="error">Error!</span>
</div>
I'm trying to get the next .error class closest to #test, if I have a #section2 and a #test2 I would want to get the .error class closest to #test2 and so on.
The nextElementSibling property returns the element immediately following the specified element, in the same tree level.
Example: Get the HTML content of the next sibling of a list item:
var x = document.getElementById("item1").nextElementSibling
The nextElementSibling property might help.
Best bet would be to search through the jQuery code and see what they did.
http://code.jquery.com/jquery-2.0.3.js
At a glance, I do see some calls to "nextSibling" and "previousSibling."
Also see here:
How to get next element using JavaScript-only?
Hope this helps!
This is the pure javascript for you:
HTML
<div id="nodes">
<div class="error">This is error Node</div>
<div class="nextElement">This is next Element</div>
</div>
Javscript:
var nodes = Array.prototype.slice.call( document.getElementById('nodes').children ),
errorNode = document.getElementsByClassName('error')[0];
var indexOfError = nodes.indexOf(errorNode);
var nextElement = nodes[indexOfError + 1];
alert(nextElement.innerText);
Here is demo
Sounds like you may be looking for document.getElementsByClassName()... if the elements with class=error are not direct siblings in the DOM, then there's not a good way to find them otherwise. It's elementary, but you can just search through the array returned by document.getElementsByClassName('error') until you find your starting element, and then you know the next item in the array will be the next element in the DOM.
See also MDN reference. Won't work in old IE, but works for all modern browsers.

Categories