Get inner text of an element - javascript

I'm trying to figure out a way to get the text following the element, in JavaScript, but without the classicals workarounds. My markup is:
<div class='el'>
<span class='fa fa-user'></span> Dollynho
</div>
I just want the word 'Dollynho', but without spliting the innerHTML of .el. I can do it this way:
var xs = document.getElementsByClassName('el')[0]
console.log(xs.split('>')[2].trim()) # => "Dollynho"
Can I do it in a cleaner way? (No-regex, pls)
Thanks in advance!

var xs = document.getElementsByClassName('el')[0];
xs.innerText;
in firefox you may need to user textContent

Iterate through all the childNodes and grab the content of the child nodes of type text, then remove the spureous \n
var childNodes = document.getElementsByClassName('el')[0].childNodes;
var textContent = "";
for(var i=0; i<childNodes.length; i++) {
if(childNodes[i].nodeType==3 ) {
textContent+=childNodes[i].data;
}
}
textContent= textContent.replace(/\r?\n|\r/g,"");
Fiddle: http://jsfiddle.net/53rx1t0o/11/

Use this in your script code if you want the html of your .el class is retrieved:
var x = $(".el").html();

You could get the text using jquery
$(".el").text()

Depending on your IE support needs you could use textContent https://developer.mozilla.org/en-US/docs/Web/API/Node.textContent
var xs = document.getElementsByClassName('el')[0]
console.log(cs.textContent) # => "Dollynho"
IE has .innerText which works similarly but with some caveats (described on the textContent page above)
http://msdn.microsoft.com/en-us/library/ie/ms533899(v=vs.85).aspx

Related

How to use JavaScript or CSS to change a string on a page

How to use JavaScript or CSS to change a string on a page.
I will have around 50 elements which contain tags separated by commas ie
<a name="tagslist">Skrillex, dubstep, dance</a>
I want to using JavaScript take each of these words and style them differently so that they don't look like they are separated by commas but on different lines. The problem is there can be a variable amount of tag lists on the page.
Is there any way i can achieve this easily?
First of all, get out of last milennium and use this HTML:
<div id="tagslist">Skrillex, dubstep, dance</div>
Then you can do this:
var elm = document.getElementById('tagslist');
elm.innerHTML = elm.innerHTML.replace(/, /g,'<br />');
You can of course do something more complex, like this:
elm.innerHTML = "<div class='tag'>"+elm.innerHTML.replace(/, /g,"</div><div class='tag'>")+"</div>";
Alternatively, you can use real DOM methods:
var elm = document.getElementById('tagslist'), tags = elm.firstChild.nodeValue.split(", "),
l = tags.length, i, div;
elm.removeChild(elm.firstChild);
for( i=0; i<l; i++) {
div = elm.appendChild(document.createElement('div'));
div.appendChild(document.createTextNode(tags[i]));
// apply styles, className, etc. to div
}
$('a[name="tagslist"]').html(function(_, html){
var arr = [],
tags = html.split(/\s*,\s*/);
for (var i=0; i<tags.length; i++)
arr.push('<div class="whatever">' + tags[i] + '</div>');
return arr.join('');
});
Consider using an existing library such as http://ivaynberg.github.com/select2/#tags
You would have to have separate anchor tags for each one for them to be styled differently. For line breaks between them, you could put br tags between them.
What you want to do is not possible. A more ideal solution would be to have the html be rendered like so:
<span class="tagslist">
Skrillex
dubstep
dance
</span>
This way, you have complete control over the styling using CSS.

Using Javascript, what is the method to get an element, based on the text between the opening and closing tags?

I'm a beginner, and couldn't find the answer after searching.
In my example, I'm looking for an
some text here
I'd want to find this particular element, so I can do stuff with it.
Edit: The only thing I know that's unique about the element for sure, is the text "some text here", that's why I want to find it based on that.
Put id on the element:
<a href="bla" onclick="dah" id='myEl'>some text here</a>
From javascript:
var myEl = document.getElementById('myEl') // gives the element
You can also use psuedo selector :contains, with the jQuery library.
Example 2
$('div:contains("test")').css('background-color', 'red');​
http://jsfiddle.net/9z5du/
Example 2
<script>
$("div:contains('John')").css("text-decoration", "underline");
</script>
If you know that the element is a link, you can first call getElementsByTagName [docs] to narrow down your search:
var elements = document.getElementsByTagName('a');
Then you have to iterate over the elements and test which one contains the next you are looking for:
var element = null;
for(var i = 0, l = elements.length; i < l; i++) {
if(elements[i].innerHTML === 'some text here') {
// found the element
element = elements[i];
break;
}
}
if(element) {
// found the element, lets do something awesome with it
}
There are multiple ways to get the content of an element, using Node#innerText (IE) or Node#textContent (W3C) is another option. You might have to trim the text first before you compare it.
If the HTML is as shown in your post,
if(elements[i].firstChild || elements[i].firstChild.nodeValue)
is even more elegant.
The MDN documentation about the DOM might be helpful.
If you can modify the HTML then adding an ID and using getElementById would be the better option.
Try this
function getit()
{
var elems = document.getElementsByTagName('a');
for(var i=0; i<elems.length; i++)
{
var text = elems[i].childNodes[0] != null ? elems[i].childNodes[0].nodeValue : '';
if(text == "some text here")
doSomethingWith(elems[i]);
}
}

get opening tag including attributes - outerHTML without innerHTML

I would like to retrieve a certain tag element with its attributes from the DOM. For example, from
<a href="#" class="class">
link text
</a>
I want to get , optionally with a closing , either as a string or some other object.
In my opinion, this would be similar to retrieving the .outerHTML without the .innerHTML.
Finally, I need this to wrap some other elements via jQuery. I tried
var elem = $('#some-element').get(0);
$('#some-other-element').wrap(elem);
but .get() returns the DOM element including its content. Also
var elem = $('#some-element').get(0);
$('#some-other-element').wrap(elem.tagName).parent().attr(elem.attributes);
fails as elem.attributes returns a NamedNodeMap which does not work with jQuery's attr() and I was not able to convert it.
Admitted that the above examples are not very senseful as they copy also the element's no-longer-unique ID. But is there any easy way? Thanks alot.
There is a way to do this without jQuery.
This also works with <br> tags, <meta> tags, and other empty tags:
tag = elem.innerHTML ? elem.outerHTML.slice(0,elem.outerHTML.indexOf(elem.innerHTML)) : elem.outerHTML;
Because innerHTML would be empty in self-closing tags, and indexOf('') always returns 0, the above modification checks for the presence of innerHTML first.
var wrapper = $('.class').clone().attr('id','').empty();
You might want to change the selector to more exactly match the <a> element you're looking for.
clone() creates a new copy of the matched element(s), optionally copying event handlers too.
I used attr to clear the element's ID so that we don't duplicate IDs.
empty() removes all child nodes (the 'innerHTML').
Here is my solution:
opentag=elem.outerHTML.slice(0, elem.outerHTML.length-elem.innerHTML.length-elem.tagName.length-3);
I suppose, that close tag is of the form: "</"+elem.tagName+">".
Unfortunately, #AaronGillion's answer isn't reliable as I said in my comment. Thank #sus. I recommend his/her way with a little change to support <self-closing tags />:
function getOpenTag(element: HTMLElement): string {
const outerHtml = element.outerHTML;
const len = outerHtml.length;
const openTagLength = outerHtml[len - 2] === '/' ? // Is self-closing tag?
len :
len - element.innerHTML.length - (element.tagName.length + 3);
// As #sus said, (element.tagName.length + 3) is the length of closing tag. It's always `</${tagName}>`. Correct?
return outerHtml.slice(0, openTagLength);
}
The code is in TypeScript. Remove types (HTMLElement and number) if you want JavaScript.
If someone is not using jQuery . . .
elem.outerHTML
"<a href="#" class="class">
link text
</a>"
elem.cloneNode().outerHTML
""
If you want to be safe for Firefox etc. released before mid-2014, use cloneNode(false) to avoid getting inner stuff.
Reference: https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode
Here's a solution I've used:
const wrap = document.createElement('div')
wrap.appendChild(target.cloneNode(true))
const openingTag = wrap.innerHTML.split('>')[0] + '>'
This can be done without any String manipulation.
Instead, you can use the element's internals and build the string yourself from there:
function getTagHTML(el) {
if (!el instanceof HTMLElement) return null;
let result = `<${el.tagName.toLowerCase()}`;
for (const attribute in el.attributes) {
if (el.attributes[attribute].nodeValue)
result += ` ${el.attributes[attribute].name}="${el.attributes[attribute].nodeValue.replace(/"/g, """)}"`
}
result += `></${el.tagName.toLowerCase()}>`;
return result;
}
console.log(getTagHTML(document.getElementById('outer')));
<div id="outer" class='i-want-"this"'>
<span>I do not want this</span>
</div>
Please note that for self-closing elements like <img /> this would give you an unwanted and incorrect closing tag. Feel free to adjust the code accordingly.
+1 for cloneNode answer above
create HTML without content
Looping over attributes
optional end tag
optional self-closing tag
function getTagHTML(el, includeClosingTag=true , selfClosing = false) {
//return el.cloneNode(false).outerHTML;
if (el.attributes)
return `<${el.localName}` +
[...el.attributes].map(
attr => ` ${attr.name}="${attr.nodeValue.replace(/"/g, """)}"`
).join`` +
`${selfClosing ? "/" : ""}>` +
(!selfClosing && includeClosingTag ? `</${el.localName}>` : "");
else
return null;
}
document.body.querySelectorAll("*:not(script)").forEach(el=>{
console.log(getTagHTML(el));
console.log(getTagHTML(el,false));
console.log(getTagHTML(el,false,true))
});
<div id="ONE" class='CLASSNAMES' attr1='"string"'>
INNERHTML
</div>
<img id="TWO" src="https://svgshare.com/i/Uhq.svg"/>
My solution using Reg Exp to replace all possible closing tags inside element attributes:
const outerHTML = div.outerHTML;
const content = outerHTML.slice(0, outerHTML.length - div.innerHTML.length);
const dummy = content.replace(/'.*?'|".*?"/g, x => 'x'.repeat(x.length));
return content.slice(0, 1 + dummy.indexOf('>'));

javascript selectors

How does one select DOM elements in javascript?
Like for example:
<div class="des">
<h1>Test</h1>
<div class="desleft">
<p>Lorem Ipsum.</p>
</div>
<div class="Right">
<button>Test</button>
</div>
</div>
Now how do i select h1? This is just a part of a bigger Page, so cannot use getElementsByTagName(), since others might get selected. Also since there might be other h1's in the document later, i cannot attach the index(body's) to above.
Is there a simple way to select, say <h1> tag which is under the classname of desleft?
I cannot use jQuery or any other libraries.
You can use this to get to your H1:
var des = document.getElementsByClassName('des')
var fc = des[0].getElementsByTagName('h1')
alert(fc[0].innerHTML)
w3.org has selectors now (http://www.w3.org/TR/selectors-api/#examples). Here are 2 different ways that worked for me on Chrome. You may want to use querySelectorAll function that returns a list.
<script type="text/javascript">
//looks for <h1> tag under <div> with className "des"
showOff1 = function() {
var x = document.querySelector(".des h1");
alert(x.innerHTML);
}
//looks for <div> tag with className "desleft" and then use previousSibling to traceback <h1> tag
showOff2 = function() {
var y = document.querySelector("div.desleft");
var z = y.previousSibling.previousSibling;
alert(z.innerHTML);
}
</script>
<body onload="showOff2();">
Use querySelectorAll
You can use querySelectorAll:
// Will return a NodeList even if there is only one element found
var heading = document.querySelectorAll('.des > h1');
heading[1].style.color = 'red'; // NodeList is similar to an array
This will return a NodeList.
or
Use querySelector to return the first element found:
var first_heading = document.querySelector('.des > h1');
first_heading.style.color = 'blue';
Commonly used with an id selector #single-header-id.
Here's a demo
getElementsByTag()
Would be a function that you can start with, and then you can filter for the DOMElements that have the class.
var h1_array = document.getElementsByTag('h1');
var h1_class_array = [];
for (var i=0, len=h1_array.length; i < len; i++) {
if (h1_array[i].className.indexOf('classname') !== -1) {
h1_class_array.push(h1_array[i]);
}
}
The .indexOf function returns -1 if the needle is not found in the haystack.
Now re-reading your question, why not just give your h1's id's ?
DOM traversal is one of javascript's glaring issues (enter jQuery).
a simple getElementById() would save you a headache, and ids on all your h1's would be much cleaner in the end than trying to formulate an algorithm to select them by other means.
If you mean to select a h1 that is before the first element of class desleft, you could always do this:
document.getElementsByClassName("desleft")[0].previousSibling.previousSibling
Example: http://jsfiddle.net/Xeon06/ZMJJk/
previousSibling needs to be called twice because of the empty text node between the two. That's why using libraries to do this stuff is really the best way to go.
var h1 = document.querySelector('.desleft').previousElementSibling;
Find element with className='desleft' using selector '.desleft'
Just move back to previous element (not to previous node!)

Javascript DOM howto?

I am a javascript noob.
I would like to select the second 'p' element of the div.box.
How do I do this?
Thanks a lot!
Tom
To get second p element of div with class box you'd do this:
var paragraph = null;
var divs = document.findElementsByTagName('div');
for (var i = 0; i < divs.length; i++) {
var div = divs[i];
if (div.class == 'box') {
var paragraphs = div.getElementsByTagName('p');
if (paragraphs.length > 1)
paragraph = paragraphs[1];
break;
}
}
The paragraph would then be in the paragraph variable (or null if it wasn't found).
However you can do this much easier with a library such as jQuery:
var paragraph = $('div.box p:eq(1)');
Without using jQuery, the basic method would be to attach an unique ID to your Dom element
<p id="second_p_elmt"> [...] </p>
and then accessing it through the getElementById() method:
<script ...>
var second_p_elmt = document.getElementById('second_p_elmt');
</script>
<script type="text/javascript">
var boxElem = document.getElementById('box'),
pElems = boxElem.getElementsByTagName('p'),
whatYouWant = pElems[1]; // [1] is the second element in the response from getElementsByTagName
</script>
You have several options. As stated above, you could use one of the excellent frameworks, like jQuery or prototype. Or you give the <p/> an ID, that you can use simply with document.getElementById().
Then, as reko_t pointed out, without the above, you must write a lengthy DOM traversing code (which is preferable, if you don't use JS frameworks elsewhere, over embedding them only for this task).
In the most recent browsers (namely, IE>=8, FF>=3.5, recent Opera and Safari > 3) you can also use this simple snippet:
var p = document.querySelectorAll("div.box p");

Categories

Resources