In JavaScript what is the right way to kill a DOM element? - javascript

I know that I can set it's style to "display: none"
However, that just hides it.
I really want to kill a DOM element and all of it's children.
The context is that I'm building a desktop-like GUI system (for learning purposes) inside of a DOM, and when a "window" is closed, I want that DIV and all it's children to be removed.
Thus, in JavaScript, how to I tell the GC "hey, get rid of this DOM element, it's no longer needed"?
Thanks!

To remove all elements, I suppose you could set element.innerHTML to an empty string (although I've never tried it myself). Otherwise, you could use element.removeChild(child), as described here.
jQuery also supports $([selector]).remove([selector]), which is more flexible in specifying which elements you want to remove at once. There's more information about jQuery remove here.

What about removeChild ?
See http://dustindiaz.com/add-and-remove-html-elements-dynamically-with-javascript/ for more information

Related

Selecting an element with no particular id, class, xpath, etc

I am currently working on writing the test automation for a web application that loads as an SWF file for our end-users, but a fully functioning Javascript version exists for the sole purpose of automation.
I have means to navigate through the application with keyboard shortcuts, but when it comes to executing click commands, I have no luck at all. Upon inspecting with Firebug/Firepath, the only value that I could find was an xpath (no id exists, no class, no anything really).
The next issue is the xpath itself.
It is:
Really brittle.
.//*[#id='flow']/div[1]/div/div[7]/div/div[3]/div[4]/div/div/div/div/div/div/div/div[3]/div[1]/img
This appears to be the xpath to the image that represents the button, not the button itself.
Executing .click() commands on the above type of xpath will do nothing until you manually hover your mouse over the button (regardless of moveToElement commands), where it will "click" the image but no functionality will run.
So I'm wondering after digging around in the actual JavaScript looking for identifiers, is there any way to select an element through any other properties? Or is there any way I can better "identify" a function? Perhaps find the xpath to the button that the image represents?
Using JUnit and Java, if that helps.
Thanks
Apparently, my comments answered the OP's question, so here goes, for reference sake:
If you need "the button itself", as you wrote in your question, use Inspect Element from the browser to find out what the actual element is you need and then simply remove from the right-hand side of your XPath expression enough axis steps until the part that remains selects the ancestor element that is the actual button element.
Now you should be able to send it a click event.
I'm afraid there won't be much we can do about the XPath statement to be "brittle", simply because you do not have an identifier to go on. That means that if the structure of the page changes, you will have to change the XPath (unless some of the ancestor elements have some notable identifiers).

Is putting an empty string in .outerHTML equivalent to remove()?

So if I have a <span class="iii"></span> container... and I use you know:
document.querySelector('.iii').outerHTML=''; it removes the span and essentially removes that span element from the DOM and everything inside of it correct? Is it really, technically deleting/removing it from the DOM? Does it perform what remove() does?
I ask this, because .remove() is a new experimental method that is not cross browser correct? I'm trying to find a cross browser way to 'remove an element', and outerHTML = ''; does that for me, but I am asking this question because it doesn't seem right. outerHTML's function isn't for deleting, (or can it be) or is it?
Edit: added .iii my bad.
There is no difference, both will remove the element from the DOM removing all event handlers and other related properties from memory when the garbage collector decides to. As for performance I wrote a quick test, http://jsperf.com/outerhtmlblank-vs-remove and it turns out that outerHTML = '' is 14% faster on Google Chrome so I would say that is better to use. Feel free to test on other browsers to confirm the results.
When you call outerHTML = '' it sets the HTML around it to nothing, then when the browser updates it's representation of the DOM it realizes that the element is now gone and removes it from the DOM whereas remove() simply removes it from the DOM.
There doesn't seem to be any significant difference between them when it comes to removing elements from the DOM. For your case they both remove the element, and that's the end of the story.
Here are the most obvious differences that come to mind (feel free to add any other ones):
outerHTML
It is a getter
It is a setter (for the setter version it can be used to either "remove" or "replace" an element)
When you're either removing or replacing an element, you don't need to know its parent like you would need to with el.parentNode.removeChild(el)
It works only with strings, which are then parsed into DOM objects
It is a property and not a method
It is supported by most Browsers
remove
It is a method
It can remove Element and Text nodes where outerHTML isn't available on text nodes
It can only work with DOM objects and not strings
You don't need to know the element's parent, instead you just remove it
It's not supported by most Browsers as it's new

is it possible to view one html element twice on the same page, or must I create a duplicate?

I am creating a site that allows viewing and editing the contents of the 'src-div' contents within the 'edit-div.' I am not editing the src-div directly, because its thumbnailed using css zoom property.
I have considered using knockout.js to bind both elements to an observable. Currently, I have implemented the feature with jquery .html() function: simply set edit-div innerhtml to src-div innerhtml on 'select', and reverse the process after changes are made to edit-div to update the src-div.
I am wondering if I really need 2 divs here, or if there is some way to actually view the same element twice on a page, and any changes made will automatically reflect in both 'views,' elimiating the need to copy innerhtml property back and forth between two elements.
essentially, this is like a mirror effect, without the flip.
the closest thing I found so far is:
http://developer.apple.com/library/safari/#documentation/InternetWeb/Conceptual/SafariVisualEffectsProgGuide/Reflections/Reflections.html
Any recommended practices for performing this task are appreciated.
(Almost) everything you see on a page has a counterpart in the DOM. Everything in the DOM gets exactly rendered one time (apart from pseudo-classes). And every node in the DOM can only have one parent (no exclusions).
Unfortunately you'll have to clone the specific node and add changes to both, as there is no copy & translate mechanism in the current CSS documentation.
If you're using jquery you can use one div and "clone" it. You can read this for more information.
http://api.jquery.com/clone/
If you set the class of the div to the same thing, you can have changes propagated to both. Then you can apply .addClass to the second div to apply a "reflected" affect (if that's your final goal).

Binding event handlers to specific elements, using bubbling (JavaScript/jQuery)

I'm working on a project that approximates the functionality of Firebug's inspector tool. That is, when mousing over elements on the page, I'd like to highlight them (by changing their background color), and when they're clicked, I'd like to execute a function that builds a CSS selector that can be used to identify them.
However, I've been running into problems related to event bubbling, and have thoroughly confused myself. Rather than walk you down that path, it might make sense just to explain what I'm trying to do and ask for some help getting started. Here are some specs:
I'm only interested in elements that contain a text node (or any descendant elements with text nodes).
When the mouse enters such an element, change its background color.
When the mouse leaves that element, change its background color back to what it was originally.
When an element is clicked, execute a function that builds a CSS selector for that element.
I don't want a mouseover on an element's margin area to count as a mouseover for that element, but for the element beneath (I think that's default browser behavior anyway?).
I can handle the code that highlights/unhighlights, and builds the CSS selector. What I'm primarily having trouble with is efficiently binding event handlers to the elements that I want to be highlightable/clickable, and avoiding/stopping bubbling so that mousing over a (<p>) element doesn't also execute the handler function on the <body>, for example. I think the right way to do this is to bind event handlers to the document element, then somehow use bubbling to only execute the bound function on the topmost element, but I don't have any idea what that code looks like, and that's really where I could use help.
I'm using jQuery, and would like to rely on that as much as possible.
You can add an event listeners to document.body. The handler function can inspect the event to figure out which element was originally targeted. If you were using the Prototype library, you would use this:
http://prototypejs.org/api/event/element
I know you're using jQuery, but I'm sure it has equivalent functionality; I'm just not as familiar with it.
This is going to be fairly problematic, because you can't directly style the text nodes in your document. That means that if you've got something like this:
<div>
Hello world how are you
<ul>
<li>First of all, it is a lovely day outside</li>
<li>Second, it's important that you
<a href='http://somewhere.else'>click here</a>
</li>
</ul>
</div>
Well when you try to restyle the text block at the head of that <div>, you'll need to do it in such a way that the rest of the <div> doesn't also get a new background color. (At least, I think that's what you're asking for.)
There's a "highlight" plugin for jQuery that you might look at as a guide to how you can replace simple text nodes with <span> tags that have some given class. The plugin is intended to let you style words/phrases that you search for, but it's not terribly complicated and you might be able to adapt it. The plugin is here: http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html

Javascript removeChild() and appendChild() VS display=none and display=block|inline

I'm developing a web application that shows some controls and descriptions dynamically (I don't want to use jQuery or other libraries).
At this moment i make appear and disappear controls using:
element.setAttribute("style", "display : inline");
and
element.setAttribute("style", "display : none");
but i'm thinking about using:
element.appendChild(childRef);
and
element.removeChild(childRef);
So, which one is the best solution in terms of system speed and elegance of the code?
Or is there a better way to go about this?
element.appendChild(childRef); and element.removeChild(childRef); both make the browser to manipulate the DOM tree while changing CSS just changes one of the attributes.
So, changing CSS is faster.
Dev Opera says
When an element has its display style set to none, it will not need to repaint, even if its contents are changed, since it is not being displayed. This can be used as an advantage. If several changes need to be made to an element or its contents, and it is not possible to combine these changes into a single repaint, the element can be set to display:none, the changes can be made, then the element can be set back to its normal display.
This will trigger two extra reflows, once when the element is hidden, and once when it is made to appear again, but the overall effect can be much faster
Another relevant article explains about reflow and repaint
Definitely go on using display properties.
They are much faster than removing/appending children, but most important they work very well in every browsers.
I know appendChild/removeChild are supposed to be well supported in IE, but sometimes on my IE7 a still get things moving around after a new element is appended (this is only my personal experience).
Regarding the way you change the display properties I would simply do a more easy and cross-browser (setAttribute is not well supported by IE6/7 an also IE8 when in IE7 mode):
element.style.display = 'none'; //for hiding an element
element.style.display = ''; //for showing that element again using its default way of displaying
Showing an element by using display = 'inline' is wrong because the element might have by default a display block way of showing like DIV tags and you are changing its way of showing to inline wich is not correct and might lead to elements in your page moving out from the places you expect them to be.
I doubt there's much in it one way or the other, and even if there is, I bet it varies by implementation (IE vs. Chrome vs. Firefox vs. ...). Both will cause reflow events in the tree.
Showing and hiding is simple and straightforward. Adding and removing can have its uses, but for the most part is probably overkill. For one thing, you have to keep a reference to it so you can add it back later, and you have to remember where you need to add it back.
But (and this is a bit off-topic) your mechanism for showing and hiding has some issues:
With your example code, things can only be inline, not inline-block or block, which would be somewhat...limiting.
Your code also completely replaces the style information on the element (and may not work on IE; see David's comment on your question), so all other styles directly applied to the element will get blown away; consider using the style property of the element instead: childRef.style.display = 'none"; and childRef.style.display = "inline"; (or block, or...). That way, you don't bludgeon any other styles on the element.
Completely removing a child from the tree (while keeping a reference to it so you can put it back later) definitely has its uses, though. For instance, when it's not in the tree, it won't be found when you're walking the tree with selectors for doing this, that, and the other; which may be helpful.
A small aside: if you happen to be dealing with user editable elements in IE (i.e. inside a document with designMode "on" or inside an element with contenteditable true), setting the CSS display property to none won't have any effect, and you'll need to remove the elements from the DOM to hide them.
The first approach is better i think which just hides and displayes but does not remove from the DOM and add again.
I would think that performance is better just updating the style.
The answer will depend on what you are using the elements for. If it is very dynamic whether they should be shown or not, it might be a solution to add/remove from DOM, but if there are a static set of elements, it might be easier to set the style. Setting the style, you also have more control of the position in the document. Adding/removing from DOM, you need to be sure it is added at the right place.
Note:
Instead of element.setAttribute("style", "display:none"); you can use element.style.display= "none"; If you use the first approach, you will remove any other style settings on the element.
I think editing the style of an element will be faster, but which is better hide the element or remove it from dom, this depends on your needs, if you need to just hide the element or remove it.
May be you don't need the user see the element but you need to do some js logic on it, so hide here will be the best.

Categories