How to get innerHTML of DIV without few inside DIV's? - javascript

I have some DIV, what contains HTML with images, styles e.t.c. I want to remove exact div's that contains id = 'quot' or className = 'quote', but i don't understand how i can get not only innerHTML of each tag. For example, < p > and < /p > which don't have innerHTML also should be included in final parsed HTML.
var bodytext = document.getElementById("div_text");
var NewText = "";
if (bodytext.hasChildNodes){
var children = bodytext.childNodes;
for (var i = 0; i < children.length; i++){
if (children[i].id != "quot" && children[i].className != "quote" && children[i].innerText != ""){
NewText = NewText + children[i].innerHTML;
}
}
HTML of source need to be parsed:
<div id="div_text">
<p>
Some Text</p>
<p>
Some Text</p>
<p>
<img alt="" src="localhost/i/1.png" /></p>
<div id="quot" class="quote" />
any text <div>text of inside div</div>
<table><tr><td>there can be table</td></tr></table>
</div>
<p>
</p>
</div>
Desired output:
<p>
Some Text</p>
<p>
Some Text</p>
<p>
<img alt="" src="localhost/i/1.png" /></p>
<p>
</p>

Just grab a reference to the targeted divs and remove them from their respective parents.
Perhaps something a little like this?
EDIT: Added code to perform operation on a clone, rather than the document itself.
div elements don't have .getElementById method, so we search for an element manually.
window.addEventListener('load', myInit, false);
function removeFromDocument()
{
// 1. take car of the element with id='quot'
var tgt = document.getElementById('quot');
var parentNode = tgt.parentNode;
parentNode.removeChild(tgt);
// 2. take care of elements whose class == 'quote'
var tgtList = document.getElementsByClassName('quote');
var i, n = tgtList.length;
for (i=0; i<n; i++)
{
// we really should be checking to ensure that there aren't nested instances of matching divs
// The following would present a problem - <div class='quote'>outer<div class='quote'>inner</div></div>
// since the first iteration of the loop would also remove the second element in the target list,
parentNode = tgtList[i].parentNode;
parentNode.removeChild(tgtList[i]);
}
// 3. remove the containing div
var container = document.getElementById('div_text');
container.outerHTML = container.innerHTML;
}
function cloneAndProcess()
{
var clonedCopy = document.getElementById('div_text').cloneNode(true);
var tgt;// = clonedCopy.getElementById('quot');
var i, n = clonedCopy.childNodes.length;
for (i=0; i<n; i++)
{
if (clonedCopy.childNodes[i].id == 'quot')
{
tgt = clonedCopy.childNodes[i];
var parentNode = tgt.parentNode;
parentNode.removeChild(tgt);
break; // done with for loop - can only have 1 element with any given id
}
}
// 2. take care of elements whose class == 'quote'
var tgtList = clonedCopy.getElementsByClassName('quote');
var i, n = tgtList.length;
for (i=0; i<n; i++)
{
// we really should be checking to ensure that there aren't nested instances of matching divs
// The following would present a problem - <div class='quote'>outer<div class='quote'>inner</div></div>
// since the first iteration of the loop would also remove the second element in the target list,
parentNode = tgtList[i].parentNode;
parentNode.removeChild(tgtList[i]);
}
// 3. remove the containing div
//var container = clonedCopy; //.getElementById('div_text');
//container.outerHTML = container.innerHTML;
console.log(clonedCopy.innerHTML);
}
function myInit()
{
cloneAndProcess();
//removeFromDocument();
}

Related

Search entire DOM for number

I need to search my entire document for a phone number, and compile a list of elements which have this phone number in them.
However I have encountered afew snags.
I can't simply do document.body.innerHTML and replace the numbers, as this messes up third party scripts.
The following will match the elements, but ONLY if they have the number within them, and nothing else:
let elements = document.querySelectorAll("a, div, p, li");
let found = [];
for (let elm in elements) {
if (elements.hasOwnProperty(elm)) {
if (elements[elm].textContent !== undefined && elements[elm].textContent.search("00000 000000") != -1) {
found.push(elements[elm]);
}
}
}
So the following element will not match:
<li class="footer__telephone">
<i class="fa fa-phone" aria-hidden="true"></i>00000 000000
</li>
Due to having the i tag in there.
Using textContent instead of text also does not work as the parent of an element will then match, but I don't want the parent.
Edit:
<div class="row-block hmpg-text">
<div class="wrapper">
<div class="container">
<div class="row">
<div class="twelvecol">
00000 000000
</div>
</div>
</div>
</div>
</div>
Lets say the above is my HTML, if I loop through all the elements and test them with testContent then the first is going to be returned as true, to containing my number, but I need the element with the class of twelvecol on it, not the parent which is 4 levels up.
Managed to find an answer, similar to what Phylogenesis said however couldn't get any of them examples working.
function replaceText(el, regex_display, regex_link) {
// Replace any links
if (el.tagName === "A") {
if (regex_link.test(el.getAttribute("href"))) {
el.setAttribute("href", el.getAttribute("href").replace(regex_link, replacement.replace(/\s/g, '')));
}
}
if (el.nodeType === 3) {
if (regex_display.test(el.data)) el.data = el.data.replace(regex_display, replacement);
if (regex_link.test(el.data)) el.data = el.data.replace(regex_link, replacement);
} else {
let children = el.childNodes;
for (let i = 0; i < children.length; i++) {
replaceText(children[i], regex_display, regex_link);
}
}
}
let bodyChildren = document.body.childNodes;
let search_display = new RegExp(search, "g");
let search_link = new RegExp(search.replace(/\s/g, ''), "g");
for (let i = 0; i < bodyChildren.length; i++) {
replaceText(bodyChildren[i], search_display, search_link);
}

Create DOM hierarchically

I have a list of keys and values and I intend to create an xml based on this information.
My list return:
1 person
2 information
3 name
3 surname
2 address
3 street
3 country
And I want to generate an xml:
<xml>
<person>
<information>
<name></name>
<surname></surname>
</information>
<address>
<street></street>
<country></country>
</address>
</person>
</xml>
I have a list of elements, while traversing these elements would create the xml document hierarchically. I already have this code:
var elements = document.getElementsByClassName('elements');
var xml = document.createElement('xml');
for (var i = 0; i < elements.length; i++) {
var key = elements[i].getAttribute('data-key');
var value = elements[i].getAttribute('data-value');
console.log(key +' -> '+ value);
// HERE: create new elements appendChild "var xml"
}
Very similar to Forty3's answer but a tad more concise and uses and XML document, not an HTML document.
Note that if document is an HTML document, then document.createElement changes the tagname to lower case, whereas if it's an XML document, the tag case is preserved. Also, in an HTML document it's reliant on support for custom and unknown tagnames, which might not be available, so better to use an XML document.
I've made up a data source, it seems it comes from the document so hopefully it reasonably approximate what you're using. I've put some minimal validation on the level, there should be more validation of the input to ensure it meets some standardised format.
function buildDoc() {
// Create an XML document to use to create the elements
var doc = document.implementation.createDocument(null, null, null);
var data = document.getElementsByClassName('elements');
var root = doc.createElement('xml');
var parent = root;
var level = 0;
var node, tagname;
for (var i=0, iLen=data.length; i<iLen; i++) {
dataNode = data[i];
node = doc.createElement(dataNode.dataset.value);
nodeLevel = dataNode.dataset.key;
// Can only add nodes at level 1 or higher
if (nodeLevel <= 0) {
console.log('Level ' + nodeLevel + ' is invalid. Can only create nodes at level 1 or higher');
return;
}
// If node at same level, is sibling of current parent
// If node at lower level, go back levels and parents to same level
// Append node, then make node the parent
if (nodeLevel <= level) {
while (nodeLevel < level) {
parent = parent.parentNode;
--level;
}
parent = parent.parentNode.appendChild(node);
// If node at higher level, is child of current parent
// Next node might higher again, so set parent to node
} else if (nodeLevel > level){
parent = parent.appendChild(node);
level = nodeLevel;
}
}
// Return the root
return root;
}
window.onload = function() {
console.log(buildDoc().outerHTML);
};
<div>
<span class="elements" data-key="1" data-value="Person">1 person</span><br>
<span class="elements" data-key="2" data-value="information">2 information</span><br>
<span class="elements" data-key="3" data-value="name">3 name</span><br>
<span class="elements" data-key="3" data-value="surname">3 surname</span><br>
<span class="elements" data-key="2" data-value="address">2 address</span><br>
<span class="elements" data-key="3" data-value="street">3 street</span><br>
<span class="elements" data-key="3" data-value="country">3 country</span><br>
<span class="elements" data-key="2" data-value="address">2 address</span><br>
<span class="elements" data-key="3" data-value="street">3 street</span><br>
<span class="elements" data-key="3" data-value="country">3 country</span><br>
</div>
PS. This probably won't run in IE 10 or lower due to lack of support for data-* attributes.
Note: this is untested and I need to step away. But, this should give you a starting point with comments.
var elements = document.getElementsByClassName('elements');
var xml = document.createElement('xml');
var curElem = xml;
var curDepth = 0;
for (var i = 0; i < elements.length; i++) {
var key = elements[i].getAttribute('data-key');
var value = elements[i].getAttribute('data-value');
console.log(key +' -> '+ value);
// HERE: create new elements appendChild "var xml"
// Create the new element
var elem = document.createElement(value);
// If we are further down the hierarchy, simply add the child
if (key > curDepth) {
curElem.appendChild(elem);
} else if (key == curDepth) {
// We are a sibling of our current containing element
// so simply add to the parent
curElem.parentElement.appendChild(elem);
curElem = elem;
} else if (key < curDepth) {
// We are at some point ABOVE our current element
// so start walking UP until we reach the level indicated
// and then add the element to the parent
while (curDepth >= key) {
curElem = curElem.parentElement;
curDepth--;
}
curElem.parentElement.appendChild(elem);
}
curElem = elem;
curDepth = key;
}

how to get elements in an element by attrbutes and update it node with purejs?

i have a html tag like this :
<div data-ctrl="master">
<div data-text="txtName"></div>
</div>
<div data-ctrl="master">
<div ><span data-text="txtName"></span> Wiratama</div>
</div>
and in js code i have :
var txtName = 'Yoza';
i want to insert html to every element in document with attribute data-text="txtName" in element with data-ctrl="master" with pure js.
function updateData(txtName){
var html = '<b>' + txtName + '</b>';
//update data for every element with attribute data-text txtName here
var allElements = document.getElementsByTagName('*');
for (var i = 0, n = allElements.length; i < n; i++) {
if (allElements[i].getAttribute("data-text") !== null) {
if (allElements[i].getAttribute("data-text") === 'txtName') {
console.log(nodeTemplate);
// allElements[i].innerHTML = html;
}
}
}
}
that is my js code i tried to.
Use querySelectorAll to return a list of nodes which match your selection. Then iterate over each of them, setting the innerHTML as you go:
function updateData(txtName){
var nodes = document.querySelectorAll('[data-ctrl="master"] [data-text="txtName"]');
for (i = 0; i < nodes.length; ++i) {
nodes[i].innerHTML = "<b>" + txtName + "</b>";
}
};
updateData("Yoza");
<div data-ctrl="master">
<div data-text="txtName"></div>
</div>
<div data-ctrl="master">
<div ><span data-text="txtName"></span> Wiratama</div>
</div>
On all modern browsers, and also IE8, you have querySelector and querySelectorAll on elements (and also on document), which accept CSS selectors. querySelector returns the first matching element (or null); querySelectorAll returns a list.
So if you have an element and want to find all of the elements within it that have the attribute data-text="txtName", you can do:
var list = theElementYouHave.querySelectorAll('[data-text="txtName"]');
So for example:
// Get some element
var element = document.getElementById("foo");
// Find all elements inside it that have `data-text` (at all)
snippet.log("Descendant elements with a data-text attribute: " +
element.querySelectorAll("[data-text]").length);
// Find the *first* element with `data-text="txtName"` and change its
// text to "Yoza":
var txtNameElement = element.querySelector('[data-text="txtName"]');
if (txtNameElement) {
txtNameElement.innerHTML = "Yoza";
}
<div id="foo">
<div data-ctrl="master">
<div data-text="txtName"></div>
</div>
<div data-ctrl="master">
<div><span data-text="txtName"></span> Wiratama</div>
</div>
</div>
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

innerHTML in DOM

I am unable to change the text inside my 'p' tag using this script
<script>
var firstItem = document.getElementByTagName('p');
firstItem.innerHTML = 'Adding Javascript';
</script>
You have several coding errors. Here's some corrected code:
<script>
var firstItem = document.getElementsByTagName('p')[0];
firstItem.innerHTML = 'Adding Javascript';
</script>
The correct method is document.getElementsByTagName('p'). Note the "s" at the end of "Elements".
Then, because document.getElementsByTagName('p') returns an HTML collection object, you have to either iterate over the collection or reach into the collection to grab a specific DOM object (which I did in my example with [0]).
And here's a working code snippet:
// change just the first <p> tag
document.getElementById("test1").addEventListener("click", function(e) {
var firstItem = document.getElementsByTagName('p')[0];
firstItem.innerHTML = 'Adding Javascript';
});
// change all the <p> tags
document.getElementById("test2").addEventListener("click", function(e) {
var items = document.getElementsByTagName('p');
for (var i = 0; i < items.length; i++) {
items[i].innerHTML = 'Setting All Items';
}
});
<button id="test1">Change text of first item</button><br><br>
<button id="test2">Change text of all items</button><br><br>
<p>This is some text</p>
<p>This is more text</p>
<p>This is and more text</p>

Stack at getting elements with javascript

I have the following html elements from which I have to get some specific texts,
example "John Doe"
I'm a newbie in javascript but have been playing with getElementById etc but I can't seem to get this one right.
<div id="name">
<p><span id="nameheading">name: </span> John Doe</p>
</div>
Bellow is What I have tried:
function askInformation()
{
var nameHeading = document.getElementById("nameheading");
var paragraph = document.getElementsByTagName("p").item(0).innerHTML ;
var name = paragraph[4];
console.log(name); // prints letter (n)
}
I need help please
If you want to get the text following the span in the following:
<div id="name">
<p><span id="nameheading">name: </span> John Doe</p>
</div>
You can use something like:
// Get a reference to the span
var span = document.getElementById('nameheading');
// Get the following text
var text = span.nextSibling.data;
However that is highly dependent on the internal structure, it may be best to loop over text node children and collect the content of all of them. You may also want to trim leading and trailing white space.
You could also get a reference to the parent DIV and use a function like the following that collects the text children and ignores child elements:
// Return the text of the child text nodes of an element,
// but not descendant element text nodes
function getChildText(element) {
var children = element.childNodes;
var text = '';
for (var i=0, iLen=children.length; i<iLen; i++) {
if (children[i].nodeType == '3') {
text += children[i].data;
}
}
return text;
}
var text = getChildText(document.getElementById('name').getElementsByTagName('p')[0]);
or more concisely for hosts that support the querySelector interface:
var text = getChildText(document.querySelector('#name p'));
var paragraph = document.getElementsByTagName("p").item(0).innerHTML ;
var name = paragraph.replace('<span id="nameheading">name: </span>','').trim(); // John Doe

Categories

Resources