getting text content of specific element - javascript

I'm trying to get element text content only ignoring element's descendants, for instance if you look at this HTML:
<p>hello <h1> World </H1> </p>
for element "P" the right output should be ONLY "hello ".
I have checked the function: "element.textContent" but this returns the textual content of a node and its descendants (in my example it will return "hello world").
Thanks,

Considering this HTML:
<div id="gettext">hello <p> not this </p> world?</div>
do you want to extract "hello" AND "world"? if yes, then:
var div = document.getElementById('gettext'), // get a reference to the element
children = [].slice.call(div.childNodes), // get all the child nodes
// and convert them to a real array
text = children.filter(function(node){
return node.nodeType === 3; // filter-out non-text nodes
})
.map(function( t ){
return t.nodeValue; // convert nodes to strings
});
console.log( text.join('') ); // text is an array of strings.
http://jsfiddle.net/U7dcw/

well behind it is an explanation
$("p").clone() //clone element
.children() //get all child elements
.remove() //remove all child elements
.end() //get back to the parent
.text();

The answer i have is the same provided in couple of other answer. However let me try and offer an explanation.
<p >hello<h1>World</h1> </p>
This line will be rendered as
hello World
If you look at this code it will be as follow
<p>hello</p>
<h1>World</h1>
<p></p>
With the <p> tag you do not necessarily need the closing </p> tag if the paragraph is followed by a element.
Check this article
Now you can select the content of the first p tag simply by using the following code
var p = document.getElementsByTagName('p');
console.log(p[0].textContent);
JS FIDDLE

You can use the childNodes property, i.e.:
var p = document.querySelector('p');
p.childNodes[0]; // => hello
jsFiddle

Change your html to
<p id="id1">hello <h1> World </h1> </p>
Use this script,
alert(document.getElementById("id1").firstChild.nodeValue);

Try to provide id for the element which you want to do some operation with that.
Below is the working example, it show output as "hello" as you expected.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function showParagraph()
{
alert(document.getElementById('test').innerHTML);
}
</script>
</head>
<body>
<p id="test">hello <h1> World </H1> </p>
<input type="button" onclick="showParagraph()" value="show paragraph" />
</body>
</html>

Plain texts are considered as nodes named #text. You can use childNodes property of element p and check the nodeName property of each item in it. You can iterate over them and select just #text nodes.
The function below loops over all element in document and prints just #text items
function myFunction()
{
var txt="";
var c=document.body.childNodes;
for (i=0; i<c.length; i++)
{
if(c[i].nodeName == "#text")
txt=txt + c[i].nodeName + "<br>";
};
return txt;
}
EDIT:
As #VisioN said in comments, using nodeType is much more safer (for browser compatibility) and recommended.

Related

Converting some text within an element to an element itself using JavaScript

Is this possible using JavaScript or JQuery, or anything else?
Say I have an HTML file like this
<div>
<p>Hello World</p>
</div>
And I want to turn "World" into a span element itself, like so (so that I can style just "World")
<div>
<p>Hello <span>World</span></p>
</div>
Since there are a lot of unknowns in your question, so I am assuming that you already know the string/word around which you want to add the html tag.
So keeping that in mind, following solution should work:
HTML:
<div>
<p id="my-text">Hello World, Again!</p>
</div>
JavaScript:
const stringToBeReplaced = "World"; // what you want to replace
const innerText = document.getElementById("my-text").innerText; //grab the text
const beginIndex = innerText.indexOf(stringToBeReplaced); // get text where string begins
// if string exists
if (beginIndex >= 0) {
const textWithTag =
"<span style='color: red'>" + stringToBeReplaced + "</span>";
const newString = innerText.replace(stringToBeReplaced, textWithTag);
// replace the text with new string
document.getElementById("my-text").innerHTML = newString;
}
Hope this is what you were asking and looking for.
https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_replace3
str.replace solves the job. The comment of #Umer Hassan is correct.

how to put element into <div> by innerHTML or other ways?

This is my code:
var turn = 1;
var boardPiece;
var piece = [];
function init() {
boardPiece = document.getElementById("pages");
while (boardPiece.firstElementChild) {
if (typeof boardPiece.firstElementChild.id != 'undefined') {
piece.push(boardPiece.firstElementChild);
}
boardPiece.removeChild(boardPiece.firstElementChild);
}
document.getElementById("content").innerHTML = piece[0]; //My problem is here
}
init();
<div id="content">
</div>
<div id="pages">
<div id="page1" class="page">
...
</div>
<div id="page2" class="page">
...
</div>
</div>
The result is a text
[object HTMLDivElement]
not an element.
What's wrong with my .innerHTML? And what is typeof piece[0]? Is it text?
You need to replace your:
document.getElementById("content").innerHTML = piece[0];
with:
document.getElementById("content").innerHTML = piece[0].innerHTML;
What you are trying to do atm is to insert element (which is an object) as a plain text.
You need to use the .innerHTML along with your piece[0] variable like,
document.getElementById("content").innerHTML = piece[0].innerHTML;
Working Fiddle: https://jsfiddle.net/gs0yy50t/
Hope this helps!
The issue is that the type of piece[0] is not a string, but a HTML element. For that reason, in order to assign it to the content's innerHTML (which is a string), JavaScript is implicitly calling the piece[0].toString() method.
When calling the toString() method in HTML nodes (like most non-string objects in JavaScript), it returns a string representing the type of the object.
If you need to add the element piece[0] as child of content, then you should do:
document.getElementById("content").innerHTML = piece[0].outerHTML;
However, if what you need is to copy the content of one element into another, you should use the property innerHTML instead:
document.getElementById("content").innerHTML = piece[0].innerHTML;
Basically, both properties are strings with the HTML code of the element but outerHTML includes the element itself in the root.

Insert span in a dom element without overwrite child nodes?

I have an HTML article with some annotations that I retrieve with SPARQL queries. These annotations refer to some text in the document, and I have to highlight this text (wrapping it in a span).
I had already asked how to wrap text in a span, but now I have a more specific problem that I do not know how to solve.
The code I wrote was:
var currentText = $("#"+v[4]["element"]+"").text();
var newText = currentText.substring(0, v[5]["start"]) + "<span class=' annotation' >" + currentText.substring(v[5]["start"], v[6]["end"]) + "</span>" + currentText.substring(v[6]["end"], currentText.length);
$("#"+v[4]["element"]+"").html(newText);
Where:
v[4]["element"] is the id of the parent element of the annotation
v[5]["start"] is the position of the first character of the annotation
v[6]["end"] is the position of the last character of the annoation
Note that start and end don't consider html tags.
In fact my mistake consists in extracting data from the node with the text() method (to be able to go back to the correct position of the annotation) and put back with the html() method; but in this manner if parent node has children nodes, they will be lost and overwritten by simple text.
Example:
having an annotation on '2003'
<p class="metadata-entry" id="k673f4141ea127b">
<span class="generated" id="bcf5791f3bcca26">Publication date (<span class="data" id="caa7b9266191929">collection</span>): </span>
2003
</p>
It becomes:
<p class="metadata-entry" id="k673f4141ea127b">
Publication date (collection):
<span class="annotation">2003</span>
</p>
I think I should work with nodes instead of simply extract and rewrite the content, but I don't know how to identify the exact point where to insert the annotation without considering html tags and without eliminating child elements.
I read something about the jQuery .contents() method, but I didn't figure out how to use it in my code.
Can anyone help me with this issue? Thank you
EDIT: Added php code to extract body of the page.
function get_doc_body(){
if (isset ($_GET ["doc_url"])) {
$doc_url = $_GET ["doc_url"];
$doc_name = $_GET ["doc_name"];
$doc = new DOMDocument;
$mock_doc = new DOMDocument;
$doc->loadHTML(file_get_contents($doc_url.'/'.$doc_name));
$doc_body = $doc->getElementsByTagName('body')->item(0);
foreach ($doc_body->childNodes as $child){
$mock_doc->appendChild($mock_doc->importNode($child, true));
}
$doc_html = $mock_doc->saveHTML();
$doc_html = str_replace ('src="images','src="'.$doc_url.'/images',$doc_html);
echo($doc_html);
}
}
Instead of doing all these, you can either use $(el).append() or $(el).prepend() for inserting the <span> tag!
$("#k673f4141ea127b").append('<span class="annotation">2003</span>');
Or, If I understand correctly, you wanna wrap the final 2003 with a span.annotation right? If that's the case, you can do:
$("#k673f4141ea127b").contents().eq(1).wrap('<span class="annotation" />');
Fiddle:
$(document).ready(function() {
$("#k673f4141ea127b").contents().eq(1).wrap('<span class="annotation" />');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="metadata-entry" id="k673f4141ea127b">
<span class="generated" id="bcf5791f3bcca26">Publication date (<span class="data" id="caa7b9266191929">collection</span>): </span>
2003
</p>
At the end my solution is in this Fiddle.
Generalizing:
var element = document.getElementById(id);
var totalText = element.textContent;
var toFindText = totalText.substring(start,end);
var toReplaceText = "<span class='annotation'>"+toFindText+"</span>";
element.innerHTML = element.innerHTML.replace(toFindText, toReplaceText);
Hope it could help someone else.
Note: This don't check if two or more annotations refers to the same node, I'm working on it right now.

JQuery: Convert to & from textarea element

I am new to JQuery & I am attempting to do some things which I am not sure I can do in JQuery.
Can I get a HTML elements type using a JQuery(or maybe even a native Javascript) function? If so, what is the name of the function?
I want to update/set a HTML elements class attribute. Would you suggest I use just plain old setAttribute() for this or should I use a JQuery function? If I should use a JQuery function whats the name of the function?
Is there a javascript function that returns a HTML elements class? Is it this.getAttribute("class");?
More experienced JQuery Programmers: How would you improve this JQuery HTML code that attempts to change elements to textarea's then back again(some functionality is missing right now):
<html>
<head>
<script type="text/javascript" src="jquery-1.6.4.js"></script>
<script type="text/javascript">
<!--
var STATE = 0;
function Toggle()
{
if (STATE==1) { convertToUpdatable(); STATE = 0; }
else { convertToStatic(); STATE = 1; }
}
function convertToUpdatable()
{
// Post: Convert all HTML elements (with the class 'updatable') to textarea HTML elements
// and store their HTML element type in the class attribute
// EG: Before: <p class="updatable"/> Hello this is some text 1 </p>
// After : <textarea class="updatable p"/> Hello this is some text 1 </textarea>
$(".updatable").each(function()
{
$(this).replaceWith("<textarea>"+$(this).text() +"</textarea>");
// TODO store this elements type in class attribute
// The below is guessing that there are jquery functions getType()
$(this).setAttribute( "class", $(this).getAttribute("class") + $(this).getType() );
});
}
function convertToStatic()
{
// Post: Find all HTML elements (with the class 'updatable'), check to see if they are part of another class aswell
// (which will be their original HTML element type) & convert the element back to that original HTML element type
$(".updatable").each(function()
{
// This uses javascript functions: how can I write this in JQuery
var type = this.getAttribute("class").replace("updatable","").replace(" ", "");
if (type == "") { alert("Updatable element had no type defined in class attribute"); return; }
$(this).replaceWith( type +$(this).text() + type );
$(this).setAttribute( "class", "updatable" );
});
}
-->
</script>
</head>
<body>
<p class="updatable"/> Hello this is some text 1 </p>
<b class="updatable"/> Hello this is some text 2 </b>
<i class="updatable"/> Hello this is some text 3 </i>
<input id="MyButton" type="button" value="Click me!" onclick="Toggle();" />
</body>
</html>
Here are links for your first three questions:
How can I determine the element type of a matched element in jQuery?
http://api.jquery.com/addClass/
http://api.jquery.com/hasClass/
Javascript:
your_element.className = 'some_class';
your_element.nodeName;

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");
});

Categories

Resources