jQuery unwrap element until content [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'm playing with the following incoming HTML structure that I don't control:
<div id="someRandom1">
<div id="someRandom2">
<div id="someRandom3">
<div id="someRandom4">
...
<p>Actual content</p>
<ul>
<li>This is a thing I need too</li>
</ul>
And this
<p>Some more content</p>
...
</div>
</div>
</div>
<p id="additionalGarbage">Don't need this</p>
</div>
What I'm trying to accomplish is to end up with the following:
<p>Actual content</p>
<ul>
<li>This is a thing I need too</li>
</ul>
And this
<p>Some more content</p>
I don't know how many divs there will be but I do know there's only one child div and the stuff inside the last div is what I need. Logic should probably be to check for a child div, get the contents and check for a child div. If another child div, do check again or else finally return the content. Every loop I've written so far crashes Chrome so I'm obviously writing it wrong. Please advise.
EDIT: After all the comments, I'll try to make this more concise in some bullets.
There's an unknown number of nested divs. (I don't have any control of this).
The child div may or may not be the first element inside the parent div.
The html structure in the deepest div needs to be kept in tact.
Bonus: minimal lines of code.

Assuming...
you have the top level (since you said you're getting it from an API)
you only need to remove the outermost divs (by tag name)
the divs targeted for removal will be the first div among its siblings (though there may be other elements with different names around it)
...you can do this:
// Assumes you have a handle on the root level
var node = $("#someRandom1");
var div = node.children("div")
while (div.length) {
node = div.first()
div = node.children("div")
}
// now node.children will be the content
alert(node.children().map(function(i, n) { return n.nodeName }).toArray())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="someRandom1">
<p class="garbage"></p>
<div id="someRandom2">
<p class="garbage"></p>
<div id="someRandom3">
<p class="garbage"></p>
<div id="someRandom4">
...
<p>Actual content</p>
<ul></ul>
<p></p>
...
</div>
</div>
<p class="garbage"></p>
</div>
<p id="additionalGarbage"></p>
</div>
This simply starts with the outermost div, and if it has at least one div div, it traverses down to that. So you end up with node being the innermost consecutive div child and node.children holds its content nodes.

This shall do the trick:
document.getElementById( 'someRandom1' ).querySelector( ':not(div)' ).parentNode.innerHTML

Related

Display one object - after clicking another object in JavaScript/HTML [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I've got a very amateur question since I am very new to coding!
I have 4 button inputs "skolefag", ""sport", "fritid", "diverse" and 4 large squares (stacked upon eachother, different colors, but you can only see the red one)
I want to switch between divs (the large squares) when i click on the different categories, so that the contents and background color of the correct/matching large square shows.
What would be the easiest technique to achieve this trough?
Sorry again and thank you in advance!
You need to use onclick attribute on you button or add a click eventListenner to it.
Then you create a function that is called by onclick="myfunction(idButton)" or by your eventListener :
function myfunction(idButton) {
document.getElementById("my-elmt-to-set-up").backgroundColor = docuement.getElementById(idbutton).backgroundColor
}
and same thing for color properties, review javascript lesson I think --> after lesson you can make some incredible interactions
Here is one solution (which I think is neat):
document.addEventListener("DOMContentLoaded", function() {
change_menu("home");
});
function change_menu(
menu_to_show
) {
['home', 'second', 'third'].forEach(function(memuee) {
document.getElementById(memuee).style.display = 'none';
});
document.getElementById(menu_to_show).style.display = 'block';
}
<div style='display: flex;font-size: 200%;'>
<div>
<div style="background:green" onclick="change_menu('home')">Home</div>
<div style="background:red" onclick="change_menu('second')">Go To Second</div>
<div style="background:blue" onclick="change_menu('third')">Go To Third</div>
</div>
<div id="home" style="background:green">
HOME PAGE
</div>
<div id="second" style="background:red">
SECOND PAGE
</div>
<div id="third" style="background:blue">
THIRD PAGE
</div>
</div>
Of course this could be further optimized by referencing "page" divs by the "button" div's ids (e.g. home_page from home_button) or grouping ids within given "wrapper" divs, using classes, etc., but I think this is the essential solution.

Get text after certain element (JavaScript or JQuery) [duplicate]

This question already has answers here:
Using .text() to retrieve only text not nested in child tags
(30 answers)
Closed 5 years ago.
Could some one give me some guidance on what's the best way to do this.
I'm trying to get all the text which is after ".main"
I know this might be simple, but it's been picking at my brain all day just before Christmas. So i thought instead of stressing myself out, I would look for some guidance.
The example code only brings back the Text in P tag but i'd like to bring back Text not in it's own element and the p tag
console.log($("#container").find(".main").next().text());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div class="main"> WOOP IN MAIN </div>
Text not in it's own element
<p> Text in P tag </p>
</div>
The simplest way to achieve this is to clone() the container, remove the .main element from it, then get the text(), like this:
var text = $("#container").clone().find('.main').remove().end().text();
console.log(text.trim());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div class="main"> WOOP IN MAIN </div>
Text not in it's own element
<p> Text in P tag </p>
</div>
You could alternatively recursively traverse through the DOM nodes that follow the .main element, but this is much more complicated and gives the same result.
It's because Text not in it's own element is considered a text node, therefore next() will target the <p/> tag, being that it's an HTMLElement. If you were to go native you'd use a combination of nextSibling, which is agnostic of the two node types and nextElementSibling, which as it's method name implies, grabs the next sibling element:
const main = document.querySelector('.main');
const txt = [
main.nextSibling.textContent.trim(),
main.nextElementSibling.textContent.trim()
];
console.log(txt)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="container">
<div class="main"> WOOP IN MAIN </div>
Text not in it's own element
<p> Text in P tag </p>
</div>

How to take the closest/nearest element of a specific class [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am trying to get the closest/nearest class of a specific element.
How can I make it work? I am currently trying to use .closest.
HTML
<div class="test">.test</div> <!-- Not this -->
<div>
<div class="test">.test</div> <!-- That's the one I need to grab -->
</div>
<div id="test"></div> <!-- This is the reference element -->
<div class="another"></div>
<div class="another"></div>
<div class="test">.test</div>
JS
var test = $('#test2').closest('.test');
console.log(test);
If closest isn't the right method, how can I actually grab the closest 'test' class?
I tried parentsUntil() as well.
Actually if that can help, in my use case I will ALWAYS need the nearest PARENT element of a specific class, whether that parent element is within another element or not, like in this HTML example.
If I understand correctly then you are looking for the nearest element that appears before a specific element in HTML source order (and you do not know/cannot change the HTML structure). The simplest solution is this:
jQuery() collections are sorted in the order in which the elements appear in DOM (unless the documentation states otherwise). So we have:
$("#test, .test")
// [div.test, div.test, div#test, div.test]
// ^ ^
// | +---- reference element
// +-------------- nearest element before it
//
// notice that the elements are sorted in the order they appear in HTML
Just combine this with jQuery.index():
$(function() {
var $ref = $("#test");
var $col = $(".test").add($ref);
var index = $col.index($ref);
$col.eq(index - 1).css("background-color", "orange");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="test">.test</div> <!-- Not this -->
<div>
<div class="test">.test</div> <!-- That's the one I need to grab -->
</div>
<div id="test"></div> <!-- This is the reference element -->
<div class="another"></div>
<div class="another"></div>
<div class="test">.test</div>
Not sure, why your HTML is structured like that, but this should select your required div:
$('.test',$('#test2').prev('div')).text() // find a div with class test, contained within div that lies previous to #test2
Closest searches for parent elements in DOM tree. For siblings you cannot easily get the nearest as such, but if you know direction up/down you can select from .nextAll('.test:first') and prevAll('.test:first').

Why does this var only select first element found? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am trying to select a specific parent of every element that has a title attribute that starts with "Mod" and put them in a single var that I can then easily control.
var allMods= $('#main-element .object[title^="Mod"]').closest('.specific-parent');
$(allMods).hide();
but it only works on the first found element, I can't understand how to set the var to be every match, can someone give me a hand please?
It should work provided all of the .object[title^="Mod"] elements are within the #main-element container.
Example: Live Copy | Source
HTML:
<div id="main-element">
<div class="specific-parent">
<div class="object" title="Mod1">Mod1 - turns green</div>
</div>
<div class="specific-parent">
<div class="object" title="Mod2">Mod2 - turns green</div>
</div>
<div class="specific-parent">
<div class="object" title="Mod3">Mod3 - turns green</div>
</div>
</div>
<div>
<div class="specific-parent">
<div class="object" title="Mod4">Mod4 - does <strong>not</strong> turn green</div>
</div>
</div>
JavaScript:
$('#main-element .object[title^="Mod"]').closest(".specific-parent").css("color", "green");
Result: Only the .specific-parents of .object[title^="Mod"] elements that are within #main-element turn green.
As per the Docs:
For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
You probably want .parents() (note the S, .parent() also returns only ONE element)

How to wrap DIV tags with different class names? [duplicate]

This question already has an answer here:
Closed 10 years ago.
Duplicate:
How can I add a parent element to a group of paragraph?
I have the following HTML blocks repeated in the document
<!-- first block -->
<div class="first">
My first div
</div>
<div class="second">
My second div
</div>
<!-- second block -->
<div class="first">
My first div
</div>
<div class="second">
My second div
</div>
...
How can I wrap the Divs with jQuery to get the resulting HTML like this...
<!-- first block -->
<div class="container">
<div class="first">
My first div
</div>
<div class="second">
My second div
</div>
</div>
<!-- second block -->
<div class="container">
<div class="first">
My first div
</div>
<div class="second">
My second div
</div>
</div>
...
You're in luck, that's exactly what wrapAll is for:
$(".first, .second").wrapAll('<div class="container"></div>');
Live Example | Source
Your edit markedly changes the question. If you need to do the above only within some containing block, you can loop through the containing blocks and apply wrapAll only to their contents. You'll need a way to identify the way you want to group your divs, which you haven't specified in the question.
If the divs have some kind of container around them, you can do this:
$(".block").each(function() {
$(this).find(".first, .second").wrapAll('<div class="container"></div>');
});
In that example, I've assumed the divs are within a container with the class "block".
Live Example | Source
If there's no structural way to identify them, you'll have to do it some other way. For instance, here we do it by assuming any time we see a first, we should stop grouping:
var current = $();
$(".first, .second").each(function() {
var $this = $(this);
if ($this.hasClass('first')) {
doTheWrap(current);
current = $();
}
current = current.add(this);
});
doTheWrap(current);
function doTheWrap(d) {
d.wrapAll('<div class="container"></div>');
}
Live Example | Source
That works because $() gives you the elements in document order, so if we loop through them in order, saving them up, and then wrap up the previous ones whenever we see a new first (and of course, clean up at the end), you get the desired result.
Or here's another way to do that same thing, which doesn't use wrapAll. It relies on the first matched element being a first (so no seconds before firsts!):
var current;
$(".first, .second").each(function() {
var $this = $(this);
if ($this.hasClass('first')) {
current = $('<div class="container"></div>').insertBefore(this);
}
current.append(this);
});
Live Example | Source
$('div').wrapAll('<div class="container" />');
would do it, but that would also wrap any other divs so perhaps:
$('.first, .second').wrapAll('<div class="container" />');
is better.

Categories