this is what an html structure of the webpage looks like:
<body>
<form>
<input type='file'/>
</form>
<div id='list'>
<div>value here<input id='delete' type='button'/></div>
</div>
</body>
i have found javascript code that triggers on 'delete' button click and removes input 'file' element. it uses this piece of code where element is input 'file' mentioned above:
deleteButton.onclick=function(){this.parentNode.element.parentNode.removeChild(
this.parentNode.element );}
i am trying to understand logic(rules) behind 'this.parentNode.element' ? why not accessing element directly 'element.parentNode.remove...'
many thanks
i am trying to understand logic(rules) behind 'this.parentNode.element' ?
There's no element property on the Node, Element, HTMLElement, or HTMLDivElement interfaces. So my guess would be that elsewhere in that code, you'll find something that's explicitly adding that property to the element instance of the div containing the button. You can do that, add arbitrary properties to element instances. These are frequently called "expando" properties and should be done very, very, very carefully.
Not the answer to the question, just opinion. It's better avoid constructions like
this.parentNode.element.parentNode
Because in case when you change your DOM structure, you will need rewrite you JS. So I think it's better to give id attributes to tags, and use next construction to get DOM element:
document.getElementById('element_id')
or if you will use some js framework (like jQuery) you can use even easier construction to get DOM element
$("#ement_id")
Ok, "removeChild" is a strange method, and quite probably, ill-conceived. It should look like:
<div>value here<input id='deleteMe' type='button'/></div>
var node = document.getElementById('deleteMe');
node.remove(); // <--- does not exist, but sure would be nice!!!
No, instead we have to do these shenanigans:
var node = document.getElementById('deleteMe');
node.parentNode.removeChild(node); // verbose! Convoluted!
We have to get the node's parent, call the method, then refer to the node again. This doesn't look like any other DOM methods as far as I recall. The good news is you can make it happen all in one line, chained, like a jQuery method.
You are best served to start over or copy somebody else's code. The use of "this" means it was within an object (or class), referring to other methods or properties within that object. You should stick to non-object variables and functions for now.
Hope that helps.
Related
Kind of a newbie to this but I have followed a totorial on a memory game as an attempt to understand the syntax of JS but am stuck on making the round result print in a instead of showing up as a alert
here is a codepen here.
how can I print round in a <span> <!-- result here--> </span> rather than like this alert("result")
How can I make it set to a span instead of being an alert?
Browsers parse HTML into a tree of objects called Document Object Model (DOM). Using JavaScript you can query the DOM to get individual nodes, and then change them.
To get your span, you would typically use document.getElementById or document.querySelector (there are other functions that can fetch collections of related nodes, like document.getElementsByClassName or document.querySelectorAll). The former identify nodes by the property named in the method name (ID, or class name, respectively); the latter ones use CSS selectors. (All of the getElement... functions can be replicated using the newer querySelector and querySelectorAll interface, though you have to know how to use CSS selectors. I almost never use getElement... functions any more.) There are also functions that use XPath, though this is a bit more advanced subject.
Once you have the node, you can change its content using e.g. .textContent or .innerHTML properties, the former being for plain text, the latter for HTML.
For example, if this is the only span on the page, this suffices:
document.querySelector('span').textContent = "Result";
<span></span>
If on the other hand you have more of them, you would need some way to target the correct one. I will also demonstrate how you can style it using HTML:
const node = document.querySelector('#result_goes_here');
node.innerHTML = "<strong>Result</strong> in bold!";
<span id="result_goes_here"></span>
If you are trying to add the result inside the HTML SPAN and not in the alert box. You can do it something like this:
document.getElementById("span_ID").innerHTML = the_variable_result_here;
Hope that helps!
Question:
In Web Components specification, when you want to read elements within a Light-DOM from the template the <content select></content> element can be used. But, how can this information be retrieved from the javascript code of the component?
Example:
<wc-timer>
<wc-timer-title>I want to read this from JS</wc-timer-title>
</wc-timer>
Thanks in advance, Javier.
Remember that this inside of your prototype methods refers to the element itself. IOW, just like you could do element.innerHTML or element.firstChild you can write this.innerHTML or this.firstChild.
Simple mode:
domReady: function() {
console.log(this.textContent);
}
http://jsbin.com/bociz/2/edit
This gets more complicated if you are using <content> to project nodes through multiple levels of Shadow DOM. In this case, you will need to use getDistributedNodes api of the <content> node itself.
Before getting into that, I suggest you start with the simple version, and ask a follow up question if you get into trouble.
Use this, for accessing lightDOM and
use this.shadowRoot to access shadowDOM
I have no idea what the template renders out as to the dom, but maybe you can try this:
//jQuery
$('wc-timer-title').text();
//Plain
document.getElementsByTagName("wc-timer-title")[0].innerHTML;
You should be able to use /deep/, it is being deprecated but there is no date as to when that will happen.
I am new to JavaScript so forgive me if the question comes around as dumb.
I know that appendChild() allows me to add a child element to an existing element. However, the problem is that I want to add an element which has an image on the left and a series of text boxes on the right and I need to add it over and over again on button click.
Adding simple elements like p, a , etc can be done by a single call to appendChild(), however for the above scenario, it will be a little messy.
Is there some way that I can define the custom element that I want to append and then just add it with a single call to appendChild()
Are you using jQuery? If it is a really complicated template, you could use .load() to ajax in an template and populate it with whatever you have to. You wouldn't need to dynamically create all of the elements using javascript, only populate it. This would would also allow you to change your template if need be very easily.
It seems you need cloneNode:
target.appendChild(template.cloneNode(true)); // If you want to clone template
// with all its descendants
target.appendChild(template.cloneNode(false)); // If you want to clone template
// without its descendants
I do this quite a bit. My code generally looks like this:
<div class="template" style="display: none;">stuff</div>
then:
$('.template').clone(true).removeClass('template').show().appendTo(someElement);
Since you're not using jQuery, have a look at the clone function here:
http://code.jquery.com/jquery-1.11.0.js
(search for "clone: function" to find it)
You can steal the relevant bits if you can't actually use jQuery itself.
This is the same question as this:
Referring to a div inside a div with the same ID as another inside another
except for one thing.
The reason there are two elements with the same ID is because I'm adding rows to a table, and I'm doing that by making a hidden div with the contents of the row as a template. I make a new div, copy the innerhtml of the template to my new div, and then I just want to edit bits of it, but all the bits have the same ID as the template.
I could dynamically create the row element by element but it's a VERY complex row, and there's only a few things that need to be changed, so it's a lot easier to just copy from a template and change the few things I need to.
So how do I refer to the elements in my copy, rather than the template?
I don't want to mess up the template itself, or I'll never be able to get at the bits for a second use.
Or is there another simpler way to solve the problem?
It will probably just be easiest when manipulating the innerHtml to do a replace on the IDs for that row. Maybe something like...
var copiedRow = templateRow.innerHTML.replace(/id=/g,"$1copy")
This will make the copied divs be prefixed with "copy". You can develop this further for the case that you have multiple copies by keeping a counter and adding that count variable to the replace() call.
When you want to make a template and use it multiple times its best to make it of DOM, in a documentFragment for example.
That way it doesn't respond to document.getElementById() calls in the "live" DOM.
I made an example here: http://jsfiddle.net/PM5544/MXHRr/
id's should be unique on the page.
PM5544...
In reality, there's no use to change the ID to something unique, even though your document may not be valid.
Browsers' selector engines treat IDs pretty much the same as class names. Thus, you may use
document.querySelector('#myCopy #idToLookFor');
to get the copy.
IDs on a page are supposed to be unique, even when you clone them from a template.
If you dynamically create content on your page, then you must change the id of your newly cloned elements to something else. If you want to access all cloned elements, but not the template, you can add a class to them, so you can refer to all elements with that class:
var clonedElement = template.cloneNode(yes); // make a deep copy
clonedElement.setAttribute("id", "somethingElse"); // change the id
clonedElement.setAttribute("class",
clonedElement.getAttribute("class") + " cloned"
);
To access all cloned elements by classname, you can use the getElementsByClassName method (available in newer browsers) or look at this answer for a more in-depth solution: How to getElementByClass instead of GetElementById with Javascript?
Alternatively, if you have jQuery available, you can do this is far less lines of code:
$("#template").clone().attr("id","somethingElse")
.addClass("cloned").appendTo("#someDiv");
The class lookup is even simpler:
$(".cloned").doSomethingWithTheseElements();
Try to avoid using IDs in the child elements of the cloned structure, as all ids of the cloned element should be changed before adding the clone to the page. Instead, you can refer to the parent element using the new id and traverse the rest of the structure using classnames. Class names do not need to be unique, so you can just leave them as they are.
If you really must use ID's (or unique "name" attributes in form fields), I can strongly suggest using a framework like jQuery or Prototype to handle the DOM traversal; otherwise, it is quite a burden to resolve all the cross-browser issues. Here is an example of some changes deeper in the structure, using jQuery:
$("#template").clone().attr("id","somethingElse")
.addClass("cloned") // add a cloned class to the top element
.find("#foo").attr("id","bar").end() // find and modify a child element
.appendTo("#someDiv"); // finally, add the node to the page
Check out my ugly but functional cheese. I wrote a function that works like getelementbyid, but you give it a start node instead of the document. Works like a charm. It may be inefficient but I have great faith in the microprocessors running today's browsers' javascript engines.
function getelement(node, findid)
{
if (node)
if (node.id)
if (node.id == findid)
return node;
node = node.firstChild;
while(node)
{
var r = getelement(node, findid);
if (r != null)
return r;
node = node.nextSibling;
}
return null;
}
When you copy the row, don't you end up having a reference to it? At that point can't you change the ID?
I'm trying to modify an HTML document, but its not the same as the DOM. However, I found that the syntax that I used with the DOM itself doesn't work with the other document. For example, I could find the title using $("title") with the DOM. However, with the document I have to use doc.find("title"). There are other, more involved changes and I'm stuck on how to proceed with this. Is there a reference I can look at? I know about the jQuery documentation, but that assumes that you're manipulating the DOM itself.
From what I've gathered the $ function assumes it's default scope for selectors is the active document. if you create jQuery objects that are not in the body of the document, the $(object).find(selector) is your best way to select within that object. The rest of the functions should work fine, at least the ones dealing with selecting, transversing and manipulation.
I should add that if the object is a jQuery object, there is no need to use the $. All the jQuery functions will be available to that object. So if you create:
var obj = $('<div>some text</div>');
you can use obj.addClass('cool) to get a jQuery object containing
<div class="cool">some text</div>
You can use jQuery on your doc by using the following
$("title", doc)
You pass the string "doc" to jQuery and it will use that instead of the DOM