I have this Javascript in a for loop:
renderAElements[i] = document.createElement ("a");
renderAElements[i].setAttribute("href", "#");
renderAElements[i].setAttribute("class", "expander");
renderAElements[i].appendChild(expand);
alert (renderAElements[i].nodeValue);
where expand is created as:
var expand = document.createTextNode("+");
The alert, which is meant to return the link text of each created element returns null. Why is this?
Because you are trying to get the nodeValue of the Element node and not the Text node.
alert (renderAElements[i].firstChild.nodeValue);
It's because the a element contains another element and not a value. If you want to get the text out of the node you'll need to do either
renderAElements.childNodes[0].nodeValue
or
renderAElements.innerText
Check this out
<head>
<script type="text/javascript">
function GetTextNode () {
var textContainer = document.getElementById ("textContainer");
var textNode = textContainer.firstChild;
alert (textNode.data);
}
</script>
</head>
<body>
<div id="textContainer">This is a simple text in the container.</div>
<button onclick="GetTextNode ()">Get the contents of the container</button>
</body>
try this alert (renderAElements[i].firstChild.nodeValue);
Related
Hi how can I extract the text of an document as an array within javascript.
It´s easy to get the innerHTML, but I do not get the text before and after the div for example.
This should be the output:
[0]=before div
[1]=innerHTML
[2]=aferHTML
[3]=before div2
[4]=innerHTML2
[5]=aferHTML2
Of the following document:
<html><head>
<body>
before div <div>innerHTML </div>aferHTML
before div2 <div>innerHTML2 </div>aferHTML2
</body></html>
I found this link, but it does not get the text before and after the elements as well:
How to get all text from all tags in one array?
You scenario is not clear. Could you please elaborate more the specific reason.
However if you want to get text from all elements in a document, kindly review this thread -> link.
By using the childNodes property you can achieve this. But for afterHtml and before div2, you need to do some extra work because they are part of the same text node.
Please take a look at the snippet below. You can remove the last element of the array manually.
const arr = [];
document.body.childNodes.forEach(node => {
arr.push(node.textContent.trim());
})
console.log(arr)
<body>
before div <div>innerHTML </div>aferHTML
before div2 <div>innerHTML2 </div>aferHTML2
</body>
Okay here's mine.
As you can see, I wrapped your HTML inside a div with a class name content.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div class="content">
before div <div>innerHTML </div>aferHTML
before div2 <div>innerHTML2 </div>aferHTML2
</div>
</body>
</html>
<script type="text/javascript">
var body = document.querySelector('.content').children;
var list = [];
for (var i = 0; i < body.length ; i++) {
var before = body[i].previousSibling.nodeValue.trim();
var inner = body[i].innerHTML;
var after = body[i].nextSibling.nodeValue.trim();
if (before && i == 0) list.push(before); //prevent duplication and empty value
list.push(inner);
if(after) list.push(after); //prevent empty value
}
console.log(list); //output
</script>
in innerHTML, you could split the string using inner.split(" ") if you like.
I have a question about DOM. Consider the following javascript code, the output will be 5.
<body>
<p>Hello</p>
<script>
function countBody() {
var childs = document.getElementsByTagName("body")[0].childNodes;
alert(childs.length);
}
window.onload = countBody;
</script>
</body>
Since I have two element nodes and two text nodes, what is the 5th node?
You have three text nodes.
Between the body start tag and the paragraph.
Between the paragraph and the script.
Between the script and the body end tag
… you could loop over childNodes and console.log() each value to see.
Just check it for yourself:
<body>
<p>Hello</p>
<script>
function countBody() {
var childs = document.getElementsByTagName("body")[0].childNodes;
console.log([].map.call(childs, function (node) { return node.textContent; }));
}
window.onload = countBody;
</script>
</body>
You have missed one text node in your counting. Please be aware that output from snippet will be different from code you have provided.
I have the following code:
<!DOCTYPE html>
<html>
<head>
<meta charset = "utf-8"/>
<script type = "text/javascript" src = "js/jquery.js" ></script>
</head>
<body>
<div id = 'div'>
<div id = "1">
</div>
<div id = "2">
</div>
</div>
</body>
</html>
My JavaScript code is:
$(document).ready(function(){
var lastcommentq = document.getElementById('div').lastChild.id;
alert(lastcommentq);
});
It should alert the id of the lastchild of the div with the id 'div' which is '2' but I am getting the alert as "undefined". I don't know what I have done wrong. Please help me.
Your elements probably have text nodes around them, so the last child node of the outer <div> won't necessarily have an "id" attribute.
I'm not sure if all browsers support it, but there's a "lastElementChild" property that explicitly gets only elements, and not things like comment nodes or text nodes. Failing that, you could just loop through the node list looking for type 1 nodes.
is this your wanted behaivour?
$(document).ready(function(){
var lastchild = $("div").last().attr("id")
alert(lastchild);
});
<div id="div">
<div id ="1">
</div>
<div id="2">
</div>
</div>
check out this fiddle for live example
http://jsfiddle.net/sHgbF/
In jquery:
$(function(){
alert($("#div :last-child").attr('id'));
});
The jQuery way:
// assuming the last child is always a div
var lastcommentq = $('#div > div:last-child').attr('id');
// alternatively
var lastcommentq0 = $('#div').children('div').last().attr('id');
The JavaScript way:
var lastcommentq = document.getElementById('div').lastElementChild.id;
Note that this works in all modern browsers and IE 9+. See lastElementChild on MDN.
this is what I would have done, but I'm not clear as to if it's what you want:
$(function () {
var lastchild = $('#div div:last-child').attr('id');
alert(lastchild);
});
http://jsfiddle.net/pFjPS/
also, I don't believe classes or ids can start with numbers, so your markup is probably not valid
edit :
HTML5 supports it, but is not generally recommended.
I would use this approach, since ID is a property and not an attribute.
$(function () {
var lastchild = $('#div div:last-child').prop('id');
alert(lastchild);
});
When I click on the p element with an onclick attribute calling the make_child function I would expect it to append a div element when ever it is clicked but it seams to be only appending a text node to the paragraph element what is the cause of this?
<script type="text/javascript">
function make_child(text, id, type) {
var text = document.createTextNode(text);
var target = document.getElementById(id);
var add = document.createElement(type);
var addtext = add.appendChild(text);
target.appendChild(addtext);
}
</script>
<p id="changeme" onclick="make_child('I have changed', 'changeme', 'div')">Click me to change</p>
change the last line to this
target.appendChild(add);
now you are appending to the correct element
Try doing target.appendChild(add) instead of target.appendChild(addtext)
Edit (more detail):
The syntax for appendChild (from MDN) is:
var child = element.appendChild(child);
Where child is the element being appended. In this case, addtext = add.appendChild(text) is set to text rather than add. Just doing target.appendChild(add) should solve this problem.
This also means the variable addtext is useless; you can remove it leaving only
add.appendChild(text)
for that line.
When I try to clone a textarea by using cloneNote(true), the cloned textarea is not editable. Does anyone know how to resolve the problem? The sample codes show as following:
<html>
<head>
<script type="text/javascript" src="/javascripts/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">
tinyMCE.init({
theme : "advanced",
mode : "textareas",
});
</script>
<script type="text/javascript">
testclonenode = {
addAbove : function (element) {
var rowEl = element.parentNode.parentNode.parentNode;
var rowElClone = rowEl.cloneNode(true);
rowEl.parentNode.insertBefore(rowElClone, rowEl);
return false;
}
};
</script>
</head>
<body>
<table>
<tr><td>
<textarea name="content" style="width:100%">this is a test </textarea>
<p> <button onclick='return testclonenode.addAbove.call(testclonenode, this);'> Add above </button>
</td></tr>
</table>
</body></html>
It does not work that way. Also, it is impossible to move a tinymce editor using dom manipulation.
The tinymce wiki states the following:
mceAddControl
Converts the specified textarea or div
into an editor instance having the
specified ID.
Example:
tinyMCE.execCommand('mceAddControl',false,'mydiv');
So when you clone a textarea there is another problem: You will have the same id twice which will result in errors accessing the right tinymce instance.
I got this to work by using an ID which is incremented each time my clone function is triggered, so
var insertslideID = 0;
function slideclone() {
$('<div class="slides"><textarea name="newslide['+insertslideID+'][slide_desc]" id="mydiv'+insertslideID+'"></textarea></div>').insertAfter('div.slides:last');
tinyMCE.execCommand('mceAddControl',false,'mydiv'+insertslideID);
insertslideID++;
}
$('input[name=addaslidebtn]').click(slideclone);
Seems to work.
A wee bit tidier, I just use a number for my id - copy1 is the name of my button - I add the new element to the end of my container.
var count = 0;
$("#copy1").click(function(){
var newId = count;
$( "#first" ).clone().appendTo( "#container" ).prop({ id: newId, });
tinyMCE.execCommand('mceAddControl',false,newId);
count++;
});
I ran into a similar problem, except my element IDs (not just textareas) could be anything, and the same ID was always appearing twice. What I did is supposed to be horribly inefficient but there was no noticeable performance loss with dozens of elements on the page.
Basically I removed the TinyMCE ID first (uses jQuery):
$(new_element).find('.mce-content-body').each(function () {
$(this).removeAttr('id');
});
Then I reinitialized TinyMCE for all relevant elements.