remove parent node while preserving child node in jsoup - html

Consider this sample code-
<div>
<outer-tag> Some Text <inner-tag> Some more text</inner-tag></outer-tag>
</div>
I want to get the following output -
<div>
<inner-tag> Some more text</inner-tag>
</div>
How do I achieve this? Thanks!

This solution will work for your current example:
String html = "<div>"
+ "<outer-tag> Some Text <inner-tag> Some more text</inner-tag></outer-tag>"
+ "</div>";
Document doc = Jsoup.parseBodyFragment(html);
for (Element _div : doc.select("div")) {
// get the unwanted outer-tag
Element outerTag = _div.select("outer-tag").first();
// delete any TextNodes that are within outer-tag
for (Node child : outerTag.childNodes()) {
if (child instanceof TextNode) child.remove();
}
// unwrap to remove outer-tag and move inner-tag to child of parent div
outerTag.unwrap();
// print the result
System.out.println(_div);
}
Result is:
<div>
<inner-tag>
Some more text
</inner-tag>
</div>

Related

Using insertBefore to insert HTML table into the correct child div

I have the following code that inserts a table into a div using insertBefore, but I'm struggling to get the positioning of the table correct:
//function creates standard HTML table
const table = createTable({ data, propertyId });
let wrapper = document.querySelector(classes.propertySummary);
wrapper.insertBefore(table, wrapper.children[1]);
Produces the following in the DOM:
<div class="summary">
<div>Where my table should sit inside</div>
<table></table>
<div></div>
</div>
Can anyone help?
wrapper.children[1] returns the second DIV inside <div class="summary">. insertBefore() inserts an element inside the element that calls insertBefore(), in this case wrapper which returns <div class="summary">. The second parameter provided to insertBefore() determines the place among, and alongside, the list of children the first parameter is placed.
The TABLE is inserted before the second DIV .children[1], positioning the TABLE after the first DIV, not inside the first DIV.
To get there dig just a bit deeper. Here's one way:
let wrapper = document.querySelector(classes.propertySummary + " div");
Appending + " div" to the querySelector(), returns ".summary div". This selects the first DIV inside <div class="summary">.
Outputs:
<div class="summary">
<div>
Where my table should sit inside
<table></table>
</div>
<div></div>
</div>
Be sure classes.propertySummary returns ".summary"—notice the preceding dot. If not, use "." + classes.propertySummary + " div" for the querySelector() parameter.
const classes = {"propertySummary": ".summary"}, data = "", propertyId = "";
function createTable (obj) {
return document.createElement("table");
}
//function creates standard HTML table
const table = createTable({ data, propertyId });
let wrapper = document.querySelector(classes.propertySummary + " div");
wrapper.insertBefore(table, wrapper.children[1]);
<div class="summary">
<div>Where my table should sit inside</div>
<div></div>
</div>
wrapper.insertBefore(table, wrapper.children[1]);
...is superfluous. appendChild():
wrapper.appendChild(table);
...produces the same result.

How to get a copy of text inside a div which is not wrapped inside any HTML tag?

I am trying to grab the text inside a div container and perform some logic based upon the text content instead of changing it. I tried to use Node.childNodes but it returns a live Nodelist instead of a copy.
Here is the DOM structure, I am trying to grab text without a container from it only.
<div class="container" >
<span >text inside span</span>
text without a container
<button>text inside button new</button>
<button>text inside button</button>
</div>
Any ideas?
EDIT:
Desired Output:
'text without a container' as a string
You can use this:
const parent = document.getElementById('parent');
const nodes = parent.childNodes;
let text = "";
for (let node of nodes) {
if (node.nodeName === '#text') {
text += node.textContent.trim();
}
}
console.log('Final result: ', text);
<div id="parent">
<span>Inside span</span>
I'm free! as a bird!
<span>I wish I was</span>
</div>
This will loop through all of the child nodes and will only extract text that is not within another element.

Using jquery to have one html element point to another

I am new to jquery and was wondering how I can point one html element equal to another. I want to make it so that whenever something in the h2 tag changes, the text within the p tags will copy the change. Below is how my tags are set up within the class fc-center.
var title = $('div.fc-center h2').text();
$('.fc-center').append('<p>'+'' +'</p>');
with the html looking something like
<div class = 'fc-center'>
<h2> text text</h2>
<p> </p>
</div>
essentially what I want to do is something like this :
$('div.fc-center p').equalto $('div.fc-center h2')
But I am not quite sure how to go about it
I propose this solution:
var title = $('.fc-center').find('h2').text();
var elementsP=$('.fc-center').find('p');
if (elementsP.length > 0) {
$.each(elementsP, function(i, val) {
$(this).empty().html(title);
});
}
https://jsfiddle.net/julian9319/grc0y6qf/1/

Accessing the text of a class that contains other elements using Cheerio

I only want to access h1's text (H1 title is here in this case), but it prints everything. I tried adding .remove('.small-title') before text(), but it didn't work.
<div class="modal-know>
<h1>
H1 title is here
<div class="small-title">
Click
Click 2
</div>
</h1>
</div>
Node.js code
var newsTitle = $2('.modal-know h1').text(); // prints out everything
console.log(newsTitle);
have a look at cheerio docs: text()
it says
including their descendants
That is the same behaviour that jQuery .text()
So maybe this answer could help you :jQuery: using .text() to retrieve only text not nested in child tags
Here you have the code I tested:
let newsTitle = $('.modal-know h1').contents()[0].nodeValue;
// solution 2:
// .clone() //clone the element
// .children() //select all the children
// .remove() //remove all the children
// .end() //again go back to selected element
// .text(); // prints out everything
//solution 3:
// .contents().filter(function(){
// return this.nodeType == 3;
// })[0].nodeValue;
console.log(newsTitle);
*in your code sample ther is a missing " in the div modal-know class
<div class="modal-know> -> <div class="modal-know">

Create div and add style

I have one big div with id="elements" and I load from JSON file new elements objects and I need that for every element create new div inside elements ( elements div should contain lot off smaller divs, for every element one small div ). How to place this small divs inside this big div one behind another ? How to add this small divs a class style ?
In Dojo (since you have the dojo tag):
var div_elements = dojo.byId("elements");
dojo.forEach(json_data.items, function(item) {
dojo.create("div", { "class":"whatever " + item.classNames }, div_elements);
});
Of course, you can put anything as the class for your div. I just provided an example. In the second argument to dojo.create, you pass in a hash containing all the properties you want that div to have.
Create a new DOM element like so:
var childDiv = document.createElement('div');
Then add to the outer div like so:
var insertedElement = div.insertBefore(childDiv, null);
You would then keep creating childDivs as you iterate over your JSON data, and inserting them into the div Node as above.
I think you need something like this:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js" ></script>
<script type="text/javascript">
$(document).ready(function(){
json_data = 'Hey';
$('#elements').append('<div class="in_elements">' + json_data + '</div>');
});
</script>
<div id="elements">
</div>
Test it
There a simple jQuery functions for that:
var box= $("#elements");
// create elements
for (var i=0; i<items.length; i++) {
var t = $("<div class=\"element\" id=\"item_"+i+"\">"+items[i]['text']+"</div>");
box.append(t);
}
That's what you where looking for?