Reading Text Between Tags - javascript

I am trying to parse some poorly written HTML that follow the below structure.
<div>
<span>stuff</span>
Lets just put text here
<span>more stuff</span>
And here too!!!
<span id="cool">even more stuff</span>
</div>
Essentially, text is between pairs of tags. I am trying to ONLY get the "Lets just put text here" and "And here too!!!" text with JavaScript. Suggestions?
Thanks.

I would use convenient array methods: Array.prototype.filter - to get text nodes only, and Array.prototype.map to get text values from those nodes:
var div = document.querySelector('div');
var textNodes = [].slice.call(div.childNodes).filter(function(el) {
return el.nodeType === 3 && el.nodeValue.trim();
});
var text = textNodes.map(function(node) {
return node.nodeValue.trim();
});
alert("Text #1: " + text[0] + "\nText #2: " + text[1]);
<div>
<span>stuff</span>
Lets just put text here
<span>more stuff</span>
And here too!!!
<span id="cool">even more stuff</span>
</div>

Related

How can I get the text of an element, excluding certain tags

I'm trying to get a phrase hyphenated (separated by syllables) with dashes. I found this page, and it hyphenates very good, but with slashes, adds a slash after every word and the quantity of syllables of every line after each of them. I injected some code to the page to get the text from the results and replace "/ " with " " and then "/" with "-", and then print it on textarea , but I get every few words a "= x syllables" message, and I need it without it. I see these messages are inside a strong tag, so I was wondering if there was a way to get all the text from the result, excepting the text inside strong tags.
Tl;dr: I need to get
Hello, world!Hello, world!Hello, world!
from this:
<div id="text">
<div>
Hello, world!
</div>
Hello, world!
<div>
Hello, world!
</div>
<span>
Not this
</span>
</div>
You're trying to use a page like an API provider using injections. You may succeed what you want, but the right way to do it is to actually make it by searching for solutions, create some logic and then write some code to do what you want.
If you just want to extract the text and exclude certain tags without white-spaces, then use DOM querySelectorAll to match what you want and exclude what you don't want with a selector like this #text :not(span), then map the textContent and finally remove white-spaces with a regular expression like this replace(/\s/g, ''):
var result = [...document.querySelectorAll('#text :not(span)')]
.map(e => e.textContent)
.join()
.replace(/\s/g, '');
console.log(result);
<div id="text">
<div>
Hello, world!
</div>
<div>
Hello, world!
</div>
<div>
Hello, world!
</div>
<span>
Not this
</span>
</div>
Now, if you want to create your own, then you'd find the very popular compromise package with the syllables plugin that you can use like this:
nlp.extend(compromiseSyllables);
function convert() {
// Get textarea text
const text = document.getElementById('text').value;
// Create npl document with the text
const doc = nlp(text);
// Get syllables array using npl syllables plugin
const syllables = doc.terms().syllables();
// Create the wanted string result using the syllables array
const result = syllables.map(({ syllables }) => syllables.join('-')).join(' ');
// Output the result
document.getElementById('result').textContent = result;
}
convert();
document.getElementById('convert').onclick = convert;
// result =>
// as se-cond ar-gu-ment e-mo-ji-fy takes an han-dler to par-se un-known e-mo-jis
<script src="https://unpkg.com/compromise"></script>
<script src="https://unpkg.com/compromise-syllables"></script>
<textarea id="text" cols="50" rows="5">
As second argument, emojify takes an handler to parse unknown emojis
</textarea>
<div>
<button id="convert">Convert</button>
</div>
<p id="result"></p>
Plain JS/DOM API style:
const nodes = document.getElementById("text").childNodes;
let buffer = [];
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i];
if ((node.nodeName !== "SPAN") && node.textContent.trim().length !== 0) {
buffer.push(node.textContent.trim());
}
}
let result = buffer.join("");
console.log(result);
<div id="text">
<div>
Hello, world!
</div>
Hello, world!
<div>
Hello, world!
</div>
<span>
Not this
</span>
</div>
Using VanillaJS:
var clonetext = document.getElementById("text").cloneNode(true);
clonetext.querySelectorAll("*:not(div)").forEach(function(v){v.remove()});
console.log(clonetext.innerText);
<div id="text">
<div>
Hello, world!
</div>
Hello, world!
<div>
Hello, world!
</div>
<span>
Not this
</span>
<a>Not this</a>
</div>
Use cloneNode function and do create new DOMCollection from #text
Remove all childs except divs
Get innerText of #text

How to wrap with <p> in first line of contenteditable div

I used below code to wrap <p> instead of <div>.
document.execCommand('defaultParagraphSeparator', false, 'p')
But I still can't wrap first line, like this "aaa".
<div id=“body-text” class=“body-text” contenteditable=“true” data-placeholder=“Body Contents">
aaa
<p>bbb</p>
<p>ccc</p>
</div>
Does anyone know how to wrap first line "aaa" with <p>?
postscript
I changed my cord using one of the answer for reference.
But now I cant type any letter. Only if I press enter first, it works. But after I press enter and make <p>, I cant type any letter again.
Where is the problem?
<div id='body-text' class='body-text' contenteditable=true data-placeholder='Body Contents' onkeydown={firstLine}></div>
<script>
firstLine(e) {
if(e.keyCode == '13') {
var div = document.getElementById('body-text')
var text = div.firstChild.textContents
div.removeChild(div.firstChild)
var p = document.createElement('p')
p.textContent = text
div.insertBefore(p, div.firstChild)
}
}
</script>
I'm using element.firstChild to select the "aaa" textNode, and creating the paragraph element which then gets prepended back into .body-text.
var pElement = document.createElement('p');
var bodyText = document.querySelector('.body-text');
var firstLine = bodyText.firstChild;
pElement.appendChild(firstLine);
bodyText.prepend(pElement);
console.log(bodyText.outerHTML)
<div class="body-text" contenteditable="true" data-placeholder="Body Contents">
aaa
<p>bbb</p>
<p>ccc</p>
</div>
note: you don't need a class and an ID... choose one
Ok, first I have to let you know that the code you provided was using those fancy quotes “ and ” you must use either this " or this '. Having said that, I have made a Snippet that uses formatBlock.
Highlight the text and click the button <p/>.
It can wrap text in a <p>, <div>, <blockquote>, <h1>, etc..
SNIPPET
<div id="body-text" class="body-text" contenteditable="true" data-placeholder="Body Contents">
aaa
<p>bbb</p>
<p>ccc</p>
</div>
<input type="button" class="p" onclick="document.execCommand('formatBlock', false, 'p')" value="<p/>" title="Insert a Paragraph Wrapped on Highlighted Text">
One way to do it is to get first text node of your div, save the text, remove that node and then create a p tag with the text from your ancient node and insert it in your div.
UPDATED
you had a little typpo problem var text = div.firstChild.textContents, there is no s it only var text = div.firstChild.textContent
see fiddle: https://jsfiddle.net/2rgLzkyj/
HTML :
<div id='body-text' class='body-text' contenteditable=true data-placeholder='Body Contents'>
aaa
<p>bbb</p>
</div>
Javascript:
var div = document.getElementById('body-text')
div.addEventListener('keydown', onKeyDown);
function onKeyDown(e) {
if (e.keyCode == '13') {
var text = div.firstChild.textContent;
div.removeChild(div.firstChild);
var p = document.createElement('p');
p.textContent = text;
div.insertBefore(p, div.firstChild);
}
}

javascript with jQuery - how to change specific Text

How can i change followed given HTML code via javascript and jQuery:
<div> <strong> unimportant text here </strong> important text here </div>
Goal is to change the Text in the <div> .... important text here </div> without touching the ...
<strong> unimportant text here </strong>
...part
Example:
*unimportant text here * important and changed text here
jsFiddle Demo
This requires having access to the parent div. I am not sure how you would like to access it, but for example, I will use an id.
<div id="d"> <strong> unimportant text here </strong> important text here </div>
This allows for the inner element to targeted. You should just use substring in order to select the latter part of the text
var AllText = $('#d').text();
var StrongElementText = $('#d strong').text();
var ImportantText = AllText.substr(StrongElementText.length);
Edit
With no way to target the element directly, it will have to be inferred (which can lead to target collision)
jsFiddle Demo Using Inferred target
$('div strong').each(function(){
var AllText = this.parentNode.innerText;
this.parentNode.innerText += " And Changed";
var StrongElementText = this.innerText;
var ImportantText = AllText.substr(StrongElementText.length);
c[0].innerHTML += ImportantText + "<br>";//shows output
});
<div>
<strong> unimportant text here </strong>
<span id="changeText">important text here</span>
</div>
$('#changeText').text= "I CHANGE THE TEXT";

jQuery find and replace string

I have somewhere on website a specific text, let's say "lollypops", and I want to replace all the occurrences of this string with "marshmellows". The problem is that I don't know where exactly the text is. I know I could do something like:
$(body).html($(body).html().replace('lollypops', 'marshmellows'));
This would probably work, but I need to rewrite as little HTML as I can, so I'm thinking something like:
search for the string
find the closest parent element
rewrite only the closest parent element
replace this even in attributes, but not all, for example replace it in class, but not in src
In example, I would have structure like this
<body>
<div>
<div>
<p>
<h1>
<a>lollypops</a>
</h1>
</p>
<span>lollypops</span>
</div>
</div>
<p>
<span class="lollypops">Hello, World!</span>
<img src="/lollypops.jpg" alt="Cool image" />
</p>
<body>
In this example, every occurrence of "lollypops" would be replaced, only <img src="... would remain the same and the only elements that would actually be manipulated would be <a> and both <span>s.
Does anybody know how to do this?
You could do something like this:
$("span, p").each(function() {
var text = $(this).text();
text = text.replace("lollypops", "marshmellows");
$(this).text(text);
});
It will be better to mark all tags with text that needs to be examined with a suitable class name.
Also, this may have performance issues. jQuery or javascript in general aren't really suitable for this kind of operations. You are better off doing it server side.
You could do something this way:
$(document.body).find('*').each(function() {
if($(this).hasClass('lollypops')){ //class replacing..many ways to do this :)
$(this).removeClass('lollypops');
$(this).addClass('marshmellows');
}
var tmp = $(this).children().remove(); //removing and saving children to a tmp obj
var text = $(this).text(); //getting just current node text
text = text.replace(/lollypops/g, "marshmellows"); //replacing every lollypops occurence with marshmellows
$(this).text(text); //setting text
$(this).append(tmp); //re-append 'foundlings'
});
example: http://jsfiddle.net/steweb/MhQZD/
You could do something like this:
HTML
<div class="element">
<span>Hi, I am Murtaza</span>
</div>
jQuery
$(".element span").text(function(index, text) {
return text.replace('am', 'am not');
});
Below is the code I used to replace some text, with colored text. It's simple, took the text and replace it within an HTML tag. It works for each words in that class tags.
$('.hightlight').each(function(){
//highlight_words('going', this);
var high = 'going';
high = high.replace(/\W/g, '');
var str = high.split(" ");
var text = $(this).text();
text = text.replace(str, "<span style='color: blue'>"+str+"</span>");
$(this).html(text);
});
var string ='my string'
var new_string = string.replace('string','new string');
alert(string);
alert(new_string);
Why you just don't add a class to the string container and then replace the inner text ? Just like in this example.
HTML:
<div>
<div>
<p>
<h1>
<a class="swapText">lollipops</a>
</h1>
</p>
<span class="swapText">lollipops</span>
</div>
</div>
<p>
<span class="lollipops">Hello, World!</span>
<img src="/lollipops.jpg" alt="Cool image" />
</p>
jQuery:
$(document).ready(function() {
$('.swapText').text("marshmallows");
});

Replace node with innerhtml

With JavaScript I want to remove a specific DOM node and replace it with the innerHTML. For example I want to change
<div>
...
<div id="t1">
this is <b> the text </b> I want to remain.
</div>
...
</div>
To
<div>
...
this is <b> the text </b> I want to remain.
...
</div>
Try this:
var oldElem = document.getElementById('t1');
oldElem.innerHTML = 'this is <b> the text </b> I want to remain.';
var parentElem = oldElem.parentNode;
var innerElem;
while (innerElem = oldElem.firstChild)
{
// insert all our children before ourselves.
parentElem.insertBefore(innerElem, oldElem);
}
parentElem.removeChild(oldElem);
There is a demo here.
This is effectively the same thing as .replaceWith() from jQuery:
$("#t1").replaceWith('this is <b> the text </b> I want to remain.');
var t1 = document.getElementById("t1");
t1.outerHTML = "this is <b> the text </b> I want to remain.";
http://youmightnotneedjquery.com/#replace_from_html
If you are using jQuery, you can try
var inner = j$("#t1").html()
$('#t1').replaceWith(inner);
This works:
var t1 = document.getElementById("t1");
t1.parentNode.innerHTML = t1.innerHTML;
Edit:
Please note that if the parent of t1 has any other children, the above will remove all those children too. The following fixes this problem:
var t1 = document.getElementById("t1");
var children = t1.childNodes;
for (var i = 0; i < children.length; i++) {
t1.parentNode.insertBefore(children[i].cloneNode(true), t1);
}
t1.parentNode.removeChild(t1);
It's very easy actually:
let span = document.getElementById('id');
span.outerHTML = span.innerHTML;
I just modified the HTML Like this.
<div>
<div id="t0">
<div id="t1">
this is <b> the text </b> I want to remain.
</div>
</div>
</div>
And you do something like
document.getElementById("t0").innerHTML = "this is <b> the text </b> I want to remain.";
Hope it works
you might want to consider using jquery if that's possible.
it would make your life way way wayyyyyyyy easier.
once you have jquery, you can easily do this via
$("#t1").html("this is <b> the text </b> I want to remain.");
and if you find it a hassle to learn, you can always start by learning the jquery selectors.
you wouldn't know why you haven't been using it all this while :)
sorry if this is not what you want exactly..
~jquery addict
Updated:
To show what html text to put inside.
This is similar to the other answers but more functional.
go.onclick = () => {
[...t1.childNodes].forEach(e => {
t1.parentElement.insertBefore(e, t1);
});
t1.remove();
go.disabled = true;
}
#t1 {
color: red;
}
<div>
<div>BEFORE</div>
<div id="t1">
this is <b> the text </b> I want to remain.
</div>
<div>AFTER</div>
<button id="go">GO</button>
</div>

Categories

Resources