Where could `appendTo()` be usable with an `htmlString`? - javascript

The API docs for appendTo list the method being able to select an HTML string for a target.
However, there seems to be no use to this since the set still includes the original elements, and the HTML string seems not to have been added anywhere in the DOM nor do I see a circumstance where it could be available.
var b = button.appendTo('<div>').appendTo('body');
b is a button, and yet it is not wrapped in a div or anything.
You can see this at http://jsfiddle.net/0dgLe5sj/
Where would it be useful to append to a HTML string (which doesn't yet exist on the page)?

appendTo() returns the item being appended.
So your code is:
var btn = button.appendTo('<div>');
btn.appendTo('body');
As you can see, you move it inside a div, then immediately move it inside the body. So you when you look at it at the end, it's inside the body.
Perhaps you meant:
var b = button.appendTo($('<div>').appendTo('body'));
which will append a div to the body and then append the btn to that div.
Updated fiddle: http://jsfiddle.net/0dgLe5sj/8/
or, if you wanted to add to the div first:
var b = button.appendTo("<div>");
b.parent().appendTo("body")
but if you combine it into a single line, you can't get the button back into the variable using .appendTo as you're adding the div to the body so you're going to get the div or the body back.
To address the 'where would this be useful part':
Being able to create detached DOM elements is extremely useful for parsing HTML strings and can also be used to 'batch' up some changes without forcing page redraws between.
Moving one button to a detached div and the back to the body doesn't have a lot of point, but it proves the principles.

Related

Javascript for deleting DIV that blurs website

There is a website with the following div:
<div class="x" style="user-select: none; filter: blur(4px);">
under this div there are a lot of other divs. I would like to know if there is any possibility to delete only this DIV with javascript. So only that one gets deleted and all the divs underneath remain.
I want to get rid of this DIV becouse this div blurs an part of the website text. Just changing the blur(4px) wont work the website has some kind of protection what refreshes this part back to original.
the reason i am searching for an possibility in javascript is because i want to automate this in the browser.(Just deleting DIV manually under developer mode works)
so far i got the following:
var div = document.getElementsByClassName('page-content');
div.remove(); //(but this does not work)
getElementsByClassName() returns a collection. Only single objects have remove() method. You have to apply one of the following:
Use brackets to specify an index of the object you want to get:
div[0].remove()
Use item() method passing the index as well:
div.item(0).remove()
Both ways are equivalent.
As an alternative, you may call querySelector() method:
const div = document.querySelector('.page-content')
It returns a single object (according to the passed CSS selector) so you can use:
div.remove()
Edit:
To remove only the covering div, you may use replaceWith() method and pass the child nodes of that div as an argument:
div.replaceWith(...div.childNodes)
If you want to keep only element nodes, use children property:
div.replaceWith(...div.children)

Why does the elements inside my div container disappear?

I have a question about browser behavior when handling the elements inside of a div container. I have an Iframe that I use to make requests to the server to run PHP files, while the parent page remains dynamic. Requests made by the parent page to the child frame determines what eventually happens to certain elements on the parent page when the server returns the results to the child frame. I've tested everything, and it all works fine, except for one noticeable glitch. If someone happens to call a function on the main page that tries to read an element inside of a div container while the child frame is making a change to any element inside the same div container, the program gives a null error. When I check the elements of the div container with the debugger, all of the elements (14 in total) inside that specific div container are gone. I'm sure I can solve the problem by querying a random element first to see if it exists, and if not, put a call back function a second later once the child frame finishes with the parent page. But I'm curious as to why all elements inside that specific div container are gone at that exact moment in the first place, since the child frame only manipulates 5 of the elements inside that div, and the parent request is looking for a completely different element that is not being manipulated by the child frame. Am I correct to assume that making changes to an element inside of a div container forces a rewrite of all the elements inside that div? All other div container elements in the body of the document remain intact, just the one div that's being changed. This is not the exact code (too much to post) but an example.
// Parent
document.getElementById("heading").innerHTML = "Where did you go?";
// Child Frame
parent.document.getElementById("pic").src = "anotherpic.jpg";
<div id ="something">
<P id = "heading">blah blah blah</p>
<img id = "pic" src = "picture.jpg">
<p id = "picname">Picture Name</p>
</div>
If the Child runs first, and the Parent tries to read an element while the child is still making changes to an element inside the div, all elements disappear when I look for them in the debugger. Any insights into this behavior are appreciated. Thanks. (Hopefully, this was not a stupid question. lol)
Please mind there is no such thing as "at the same time" here. Both, the innerHTML and getElementById work synchronously.
Even if you used the innerHTML improperly (which I know isn't the case) eg. overriding the parent component - there's no "in-between state" that you'd be able to access with the functions, to notice that there are no elements for a "moment". So I'd look elsewhere to find a reason behind it.
eg. the Iframe content modifies the parent twice every time, first of which makes it empty.
Have you tried using:
target.addEventListener(type, listener [, options]);
Instead of:
getElementById
?
Looks like something is getting overwritten.

Is there anything wrong with adding an HTML element as a direct child of document.documentElement?

I'm writing a chrome extension, part of the functionality of which requires me to hide every html element at times with the exception of one div which I've created. (I hide everything and add the div to the current website in javascript) Because setting document.body.style.display = "none" will not allow any of the body's children to be seen, I need to add the child that I want to be seen somewhere else. (I also tried using style.visibility but for some reason that didn't hide certain HTML elements/backgrounds on certain pages.) My fix is to add the div to document.documentElement, outside of document.body. This fix actually works perfectly, but seems strange. Is there anything wrong with adding a new child to the elements? Am I doing something wrong?
EDIT: A few answers have used the children of document.body, so I thought I should note that my code has to run at document_start, and though I wait for document.body to load before executing, I can't wait for all of its children to load. Hence I can't use/store the children of document.body.
Also, I'm grateful for all the answers providing alternate solutions, they're quite useful. But out of curiosity, does anybody know if there's anything wrong with what I'm currently doing? Why is it working, if so?
The W3C specification of HTML document structure says that it consists of the <head> and <body> elements, and the <body> contains the content that's intended to be rendered. Nothing is stated about elements outside these two elements.
If it seems to work it's probably just an accident of implementation -- for instances, many implementations are forgiving of things like malformed HTML.
It's perfectly fine to append elements or text nodes directly to document.documentElement.
DOM is not HTML, it has its own specification, which - being an Object Model - is naturally quite permissive:
document.documentElement is an Element [spec]:
The document element of a document is the element whose parent is that document, if it exists, and null otherwise.
Elements are allowed to have these children [spec]:
Zero or more nodes each of which is Element, Text, ProcessingInstruction, or Comment.
Create a new DIV to hold the children of the body, and hide that.
var saveDiv = document.createElement("DIV");
saveDiv.id = "saveDiv";
saveDiv.style.display = "none";
Array.from(document.body.children).forEach(el => saveDiv.appendChild(el));
document.body.appendChild(saveDiv);
A potential solution:
const body = document.querySelector('body');
body.innerHTML = `<div class="my-div"></div><div class="content">${body.innerHTML}</div>`;
Now you have the body content all snug alongside your div, both of which you can hide/show. As pointed out below, I completely spaced that this will destroy your listeners. If you want to preserve listeners, try the following:
const body = document.querySelector('body');
const fragment = document.createDocumentFragment();
const hideBody = () => {
for (let el of [...body.children]) (fragment.append(el))
}
const showBody = () => {
for (let el of [...fragment.children]) (body.append(el))
}
Attach the appropriate one to whatever your event is. This will preserve all your listeners. If you need any functionality, DocumentFragment has the querySelector() and querySelectorAll() methods.
Another method is the modal method, where you just have a div that covers the whole page. Check out the Bootstrap modals, for example. If you initialize it with data-backdrop="static" and data-keyboard="false" then it won't disappear by clicking outside or hitting esc. The element can be selected with document.querySelector('.modal-backdrop'). Set the opacity to 1 and the background to white or whatever aesthetic you're going for.

How do I convert an XML DOM element into an HTML DOM element?

I am trying to use an XMLHTTPRequest to download an .xml file and add some of it's elements to the page as content. What I have done is to make the request, get the document, get the specific DOM elements from the xml that I want to import, use existing.appendChild(fromXML) to append the element from the xml DOM to the element in the HTML DOM.
However, none of the actual tags are rendered. The text inside each of the tags is rendered just fine. But the tags themselves seem to be ignored.
Firebug shows the added tags in the HTML panel in light blue font rather than normal blue for other tags, but I haven't been able to figure out what that means. The webkit developer tools also shows me that the tags are there (no special coloring, though), but they are not rendered properly (img and a tags don't have any effect at all, for example).
Am I missing some conversion from XML DOM to HTML DOM?
Here is a simple version of my code with comments for brevity:
// Make xmlHTTPRequest
...
// Get items from the response xml
var items = xhr.responseXML.getElementsByTagName("item");
// Get one item and it's children recursively
var elm = document.importNode(items[0],true);
// Get the existing element to add the item add to
existingDomElement = document.getElementById("demo");
for (var i = 0; i < $(elm).children().length; i++) {
var child = $($(safeChild).children()[i])[0];
existingDomElement.appendChild(child);
}
Apparently, it’s been done before, see this question. That poster’s code seems to work, but he wants something more elegant and concise. He seems to be one step ahead of you in that at least.
But the only suggestion there is to serialize the whole thing to text, and then parse it in the current tree — which might not necessarily work in your case anyway, since XML might not always parse correctly as HTML...

JQuery DOM creation/handling issue

So, say I have selected, in JQuery, a singular DOM div.
I then proceed to create a new DIV like so:
var DIV = $("<div>Hello, world</div>");
After that, I attempt to place that DIV inside the original one like so:
$(OriginalDiv).append(DIV);
Okay, that works.
Now I want to edit DIV further.
Calls to .click, .html, .addClass, (And likely more) do not work!
Okay, instead I do:
var OriginalDiv = $("someSelector");
var DIV = $("<div>Hello, world</div>");
DIV = $(OriginalDiv).append(DIV);
That appears to work at first; However, instead, it sets DIV to reference the same DOM object as OriginalDiv and NOT the newly appended DOM object. Naturally, this does not allow me to edit DIV.
So, then, I try two more methods:
var OriginalDiv = $("someSelector");
var DIV = $("<div>Hello, world</div>");
$(DIV).appendTo(OriginalDiv);
and
var OriginalDiv = $("someSelector");
var DIV = $("<div>Hello, world</div>");
DIV = $(DIV).appendTo(OriginalDiv);
Not even these work.
If I haven't done a very good job explaining, here is my exact dilemma
I am trying to create a DOM object in jquery, then append it to another DOM object using jquery. The problem is, once it gets appended, there seems to be no way for me to directly access it without using somethign like .children.
I'd like very much to be directly returned somewhere along in that process a reference to the DOM object which I am appending. As in the one that actually gets appended.
I'm not sure how to do this in JQuery. Anybody know a solution?
Thanks
--G
Yes, append won't work as it returns a reference to the element the new element was appended to. jQuery supports method chaining, so this should work easily:
$("<div>Hello, world</div>")
.click(function() {
// something
})
.appendTo('someSelector');
But even
var $ele = $("<div>Hello, world</div>").appendTo('someSelector');
will work. appendTo returns a reference to the element which was appended. If this does not work for you, you have your problem elsewhere.
Comments on your code: This is not your problem, however it is important for you to know what is going on here.
This part
var OriginalDiv = $("someSelector");
var DIV = $("<div>Hello, world</div>");
$(DIV).appendTo(OriginalDiv);
is the same as
$($("<div>Hello, world</div>")).appendTo($("someSelector"));
You see, you have a nested call to jQuery, because DIV is already a jQuery object. There is no need to pass it again to jQuery.
You can also pass a selector directly to appendTo.
you could try this;
var DIV = document.createElement('div');
then you can use;
$(div).html('Test!');
or what ever you want to use with.
You don't have to get anything back from the DOM. Once you create the element with jQuery, you already have a reference to the DOM element. Inserting it into the document does not do anything special.
// this will create the DOM element, and the jQuery
// object wrapping that newly created DOM object
// is assigned to DIV.
var DIV = $("<div>Hello, world</div>");
// Don't worry about getting a return value from this
// append() call. What we need is already available inside
// the variable DIV.
$(OriginalDiv).append(DIV);
// continue using DIV as you normally would. It is referring
// to the same DOM object that was just appended to the document.
DIV.addClass('green');

Categories

Resources