I would like to modify an element of my xml. I have to query it to find it, and then I only seem to be able to modify a copy of it. I use: clientXML.querySelector("[id=XMLIssue-9]").childNodes[2].textContent; to isolate the element in question.
I would like to just replace the element with this one newXMLIssue.childNodes[0]. They both have the exact same structure. I cant do:
clientXML.querySelector("[id=XMLIssue-9]") = newXMLIssue.childNodes[0];
because it causes an error to have the function on the left side of the equation. I also tried:
var x = clientXML.querySelector("[id=XMLIssue-9]");
x = newXMLIssue.childNodes[0];
but this only changes a copy of the element.
You have to call replaceChild on the parent:
var parent = clientXML.querySelector("[id=XMLIssue-9]");
parent.replaceChild(parent.childNodes[0], parent.childNodes[2]);
Related
Snippet of HTML code I need to retrieve values from:
<div class="elgg-foot">
<input type="hidden" value="41" name="guid">
<input class="elgg-button elgg-button-submit" type="submit" value="Save">
</div>
I need to get the value 41, which is simple enough with:
var x = document.getElementsByTagName("input")[0];
var y = x.attributes[1].value;
However I need to make sure I'm actually retrieving values from inside "elgg-foot", because there are multiple div classes in the HTML code.
I can get the class like this:
var a = document.getElementsByClassName("elgg-foot")[0];
And then I tried to combine it in various ways with var x, but I don't really know the syntax/logic to do it.
For example:
var full = a.getElementsByTagName("input")[0];
So: Retrieve value 41 from inside unique class elg-foot.
I spent hours googling for this, but couldn't find a solution (partly because I don't know exactly what to search for)
Edit: Thanks for the answers everyone, they all seem to work. I almost had it working myself, just forgot a [0] somewhere in my original code. Appreciate the JQuery as well, never used it before :-)
The easiest way is to use jQuery and use CSS selectors:
$(".elgg-foot") will indeed always get you an element with class "elgg-foot", but if you go one step further, you can use descendent selectors:
$(".elgg-foot input[name='guid']").val()
That ensures that you only get the input named guid that is a child of the element labelled with class elgg-foot.
The equivalent in modern browsers is the native querySelectorAll method:
document.querySelectorAll(".elgg-foot input[name='guid']")
or you can do what you have yourself:
var x = document.getElementsByClassName("elgg-foot")
var y = x.getElementsByTagName("input")[0];
Assuming you know it is always the first input within the div
You can combine it like this:
var a = document.getElementsByClassName("elgg-foot")[0];
var b = a.getElementsByTagName("input")[0];
var attribute = b.attributes[1].value;
console.log(attribute); // print 41
Think of the DOM as the tree that it is. You can get elements from elements in the same way you get from the root (the document).
You can use querySelector like
var x = document.querySelector(".elgg-foot input");
var y = x.value;
query the dom by selector https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
var fourty1 = document.querySelector('.elgg-foot input[name=guid]').value;
querySelector will return the first match from the selector. This selector will find the element with class elgg-foot and then look at the input element inside of that for one named guid and then take the value of the selected element.
I think the simplest way would be using JQuery. But using only javascript,
the simplest way would be:
var div = document.getElementsByClassName("elgg-foot")[0];
var input = div.getElementsByTagName("input")[0];
alert(input.value)
Take a look at this JSFiddle here: http://jsfiddle.net/2oa5evro/
I have an HTML document, and I would like to remove some of the tags from it dynamically using Javascript, based on whether the tags are within the current selection or not. However, I do not want to update the actual document on the page, I want to make a copy of the whole page's HTML and edit that copy. The problem is that the Range object I get from selection.getRangeAt(0) still points to the original document, as far as I can see.
I've managed to get editing the original document in place with this code:
var node = window.getSelection().getRangeAt(0).commonAncestorContainer;
var allWithinRangeOfParent = node.getElementsByTagName("*");
for (var i=0, el; el = allWithinRangeParent[i]; i++) {
// The second parameter says to include the element
// even if it's not fully selected
if (selection.containsNode(el, true) ) {
el.remove();
}
}
But what I want to do is to somehow perform the same operation with removing elements, but remove them from a copy of the original HTML. I've made the copy like this: var fullDocument = $('html').clone(); How could I accomplish this?
Either dynamically add a class or data attribute to all your elements on load before you clone so that you have a point of reference then grab the class or data attribute on the common ancestor and remove it from the clone. I can give an example if you like? Along these lines - http://jsfiddle.net/9s9hpc2v/ isn't properly working exactly right but you get the gist.
$('*').each(function(i){
$(this).attr('data-uniqueId', i);
});
var theclone = $('#foo').clone();
function laa(){
var node = window.getSelection().getRangeAt(0).commonAncestorContainer;
if(node.getElementsByTagName){
var allWithinRangeOfParent = $(node).find('*');
console.log(allWithinRangeOfParent, $(allWithinRangeOfParent).attr('data-uniqueId'));
$.each(allWithinRangeOfParent, function(){
theclone.find('[data-uniqueId="'+$(this).attr('data-uniqueId')+'"]').remove();
});
console.log(theclone.html());
}
}
$('button').click(laa);
I select an element of the page:
$mainSection = $('#main');
then I add more Elements via AJAX into the <div id="main"></div> element. Next time I call $mainSection, the newly added elements are also in it. But I don't want that. I would like that the variable $mainSection only has the content in it from the initial rendering of the page. I can't find a way to prevent jQuery from updating.
I tried this:
$(document).ready(function(){
$mainSection = $('#main').clone(true);
Then I add new elements to #main and then I check if they get found via:
$foundElement = $($mainSection + ":not(:has(*)):not(script):contains('"+newlyAddedContent+"')");
On page load, they are not there. But after I add them, they get found.
I also tried:
$mainSection = $('#main').html();
$mainSection = $($mainSection);
didn't work also.
Here is a jsFiddle to illustrate my point:
http://jsfiddle.net/VEQ2E/2/
The problem is somewhere burried in this line:
$foundElement = $($mainSection + ":not(:has(*)):not(script):contains('"+newlyAddedContent+"')");
It somehow always searches through the whole document, when I do it like this.
You can use .clone(true):
$mainSection = $('#main').clone(true);
It every time takes the clone/copy of the initial state of this div.
Note:
.clone( [withDataAndEvents ] [, deepWithDataAndEvents ] )
withDataAndEvents : Boolean (default: false)
deepWithDataAndEvents : Boolean (default: value of withDataAndEvents)
A Boolean indicating whether event handlers and data for all children of the cloned element should be copied.
Your problem was not that your clone was getting changed, but rather the selector you were using to try finding something within the clone. Your code was like this:
$($mainSection + ":not(:has(*)):not(script):contains('"+newlyAddedContent+"')");
Concatenating an object with a string will turn the object into a string, simply "[object Object]", then your selector will just look at the ":not(:has..."
Instead, you should use filter:
$foundElement = $mainClone.filter(":not(:has(*)):not(script):contains('world')");
This will now only look within your $mainClone for items matching that filter.
JSFiddle
You can take several approaches:
Cache the contents of #main before the update. This gives you just the contents of the element without the element.:
mainsectionContents = $('#main').html();
Or Cache a copy of #main before the update. This will give you the content together with the element, and depending on whatever else you may want to copy feel free to check the api docs:
$mainsectionCopy = $('#main').clone();
Can someone please explain to me, why
var Node = document.createElement("testing");
var Parent = document.createElement("testingOne")
Parent.appendChild(document.createElement("hi"));
Node.appendChild(Parent);
produces a different result from
var Node = document.createElement("testing");
var Parent = document.createElement("testingOne")
.appendChild(document.createElement("hi"));
Node.appendChild(Parent);
In the second snippet the element testingOne doesn't even get included. Why does the piping do this?
Your first example will result in
<testing><testingone><hi></hi></testingone></testing>
Parent will contain the testingOne and the hi element will be appended to it.
While the second example will result in
<testing><hi></hi></testing>
Because Parent will contain the hi element, which is returned by the appendChild method.
I am trying to convert my jQuery script into javascript. I have a problem there..
I have a script that creates a node
var new_node = document.createElement("div");
new_node.className="tooltip";
new_node.innerHTML = html;
alert(new_node.className);
When i do this
jQuery(link).after(new_node);
It works fine. But I want to do it javascript way. I have tried using appendChild function but it gives some strange results.
Please help me out with this.
You're comparing jQuery's after with appendChild, but they do very different things. after puts the element after the reference element, appendChild puts it inside it.
You probably want insertBefore (with the reference node being link's nextSibling).
So:
var link = /* ... get the `a` element from somewhere ... */;
var new_node = document.createElement("div");
new_node.className="tooltip";
new_node.innerHTML = html;
link.parentNode.insertBefore(new_node, link.nextSibling);
If link is the last thing in its parent, that's fine; link.nextSibling will be null and insertBefore accepts null as the reference node (it means "insert at the end").
Assuming you already have a node instantiated as link, you could do what you want this way in plain Javascript:
link.parentNode.appendChild(new_node);
The link node would have to be the last node in its container. Otherwise you would have to find link's nextSibling and use insertBefore to put new_node in its proper place.
jQuery(link).append(new_node);