I have a java script file that is used in several places. It has this code:
var newDiv = lastDiv.cloneNode(true);
lastDiv has some <input> elements that I do not want to clone. I've created these input elements with the attribute <input copy="dont"> so that I could remove them out using the following code:
newDiv.select("input[copy=dont]").remove()
The prototype.js select() finds these elements. But remove() does not work, newDiv still has the input elements that I wanted filtered. Prototype documentation states that it will remove from the document, but newDiv is not in the document, it is only in memory.
This is solved now: select() was returning an array. If only prototype would have returned a meaningful error message. It was returning the list of matching elements. Thanks for your answers guys. Will use valid HTML5. This works now
newDiv.select("input[copy=dont]")[0].remove()
i think it's just a type in your selector , try this:
newDiv.select("input[copy='dont']").remove()
also , just s suggestion , use the attribute data-copy instead of copy ex.
<input data-copy="dont" type="text" />
this will keep your elements valid HTML5
Related
How can I get a collection of elements by specifying their id attribute? I want to get the name of all the tags which have the same id in the html.
I want to use ONLY getElementById() to get an array of elements. How can I do this?
I know this is an old question and that an HTML page with multiple identical IDs is invalid. However, I ran into this issues while needing to scrape and reformat someone else's API's HTML documentation that contained duplicate IDs (invalid HTML).
So for anyone else, here is the code I used to work around the issue using querySelectorAll:
var elms = document.querySelectorAll("[id='duplicateID']");
for(var i = 0; i < elms.length; i++)
elms[i].style.display='none'; // <-- whatever you need to do here.
The HTML spec requires the id attribute to be unique in a page:
[T]he id attribute value must be unique amongst all the IDs in the element's tree
If you have several elements with the same ID, your HTML is not valid.
So, document.getElementById should only ever return one element. You can't make it return multiple elements.
There are a couple of related functions that will return a list of elements: getElementsByName or getElementsByClassName that may be more suited to your requirements.
Why you would want to do this is beyond me, since id is supposed to be unique in a document. However, browsers tend to be quite lax on this, so if you really must use getElementById for this purpose, you can do it like this:
function whywouldyoudothis() {
var n = document.getElementById("non-unique-id");
var a = [];
var i;
while(n) {
a.push(n);
n.id = "a-different-id";
n = document.getElementById("non-unique-id");
}
for(i = 0;i < a.length; ++i) {
a[i].id = "non-unique-id";
}
return a;
}
However, this is silly, and I wouldn't trust this to work on all browsers forever. Although the HTML DOM spec defines id as readwrite, a validating browser will complain if faced with more than one element with the same id.
EDIT: Given a valid document, the same effect could be achieved thus:
function getElementsById(id) {
return [document.getElementById(id)];
}
document.querySelectorAll("#yourId"); returns all elements whose id is yourId
It is illegal to have multiple elements with the same id. The id is used as an individual identifier. For groups of elements, use class, and getElementsByClassName instead.
The id is supposed to be unique, use the attribute "name" and "getelementsbyname" instead, and you'll have your array.
As others have stated, you shouldn't have the same ID more than once in your HTML, however... elements with an ID are attached to the document object and to window on Internet Explorer. Refer to:
Do DOM tree elements with ids become global variables?
If more than one element with the same ID exists in your HTML, this property is attached as an array. I'm sorry, but I don't know where to look if this is the standard behavior or at least you get the same behavior between browsers, which I doubt.
Class is more than enough for refering anything you want, because it can have a naming with one of more words:
<input class="special use">
<input class="normal use">
<input class="no use">
<input class="special treatment">
<input class="normal treatment">
<input class="no special treatment">
<input class="use treatment">
that's the way you can apply different styles with css (and Bootstrap is the best example of it) and of course you may call
document.getElementsByClassName("special");
document.getElementsByClassName("use");
document.getElementsByClassName("treatment");
document.getElementsByClassName("no");
document.getElementsByClassName("normal");
and so on for any grouping you need.
Now, in the very last case you really want to group elements by id. You may use and refer to elements using a numerically similar, but not equal id:
<input id=1>
<input id="+1">
<input id="-1">
<input id="1 ">
<input id=" 1">
<input id="0x1">
<input id="1.">
<input id="1.0">
<input id="01.0">
<input id="001">
That way you can, knowing the numeric id, access and get an element by just adding extra non-invalidating numeric characters and calling a function to get (by parsing and so on) the original index from its legal string identifying value. It is useful for when you:
Have several rows with similar elements and want to handle its events
coherently. No matter if you delete one or almost all of them.
Since numeric reference is still present, you can then reuse them and
reassign its deleted format.
Run out of class, name and tagname identifiers.
Although you can use spaces and other common signs even when it's a not a requirement strictly validated in browsers, it's not recommended to use them, specially if you are going to send that data in other formats like JSON. You may even handle such things with PHP, but this is a bad practice tending to filthy programming practices.
This is my solution:
<script type="text/javascript">
$(document).ready(function () {
document.getElementsByName("mail")[0].value = "ex_mail1";
document.getElementsByName("mail")[1].value = "ex_mail2";
});
</script>
Or you can use for-loop for that.
You shouldn't do that and even if it's possible it's not reliable and prone to cause issues.
Reason being that an ID is unique on the page. i.e. you cannot have more than 1 element on the page with the same ID.
you can use
document.document.querySelectorAll("#divId")
we can use document.forms[0].Controlid
If you're using d3 for handling multiple objects with the same class / id
You can remove a subset of class elements by using d3.selectAll(".classname");
For example the donut graph here on http://medcorp.co.nz utilizes copies of an arc object with class name "arc" and there's a single line of d3, d3.selectAll(".arc").remove(); to remove all those objects;
using document.getElementById("arc").remove(); only removes a single element and would have to be called multiple times (as is with the suggestions above he creates a loop to remove the objects n times)
I have a hidden textbox with id in the form of a part of a collection. I use the ID in this way so as to have them bind to my model. This is the simplified version of my code.
<input id="Model.Bed[0].Id" name="Model.Bed[0].Id" type="hidden" value="bed1">
I am using Jquery to remove it but while it does not throw any error, it does not get deleted. This is my code.
$('#Model.Bed[0].Id').remove();
Am I missing something?
Your jQuery selector returns 0 items because it is an invalid selector expression( [ has a different meaning)
Try the name selector. This should work
$("[name='Model.Bed[0].Id']").remove();
Keep in mind that it is allowed to have more than one element with same name attribute value. So use based on your DOM.
Also, If you have this input element generated in a loop and you have some button inside this loop for executing your remove code, you should consider using relative selectors. closest() and find() methods are handy in this case.
For example,
// Register click event with element with css class "someDeleteBtn"
$(".someDeleteBtn").click(function(e){
e.preventDefault();
$(this).closest(".containerDiv") //get to outside container
.find(".myHdnBed") // find the hidden input with this css class
.remove(); // remove
});
To escape special characters in an ID selector, you can use \ like so:
$('#Model\\.Bed\\[0\\]\\.Id').remove();
which works: http://codepen.io/anon/pen/XpqJxV
Read more here: https://learn.jquery.com/using-jquery-core/faq/how-do-i-select-an-element-by-an-id-that-has-characters-used-in-css-notation/
In the end though, you really shouldn't have a value like that as an ID in the first place.
I have the following code:
var golden_site = '<div id="golden_site"></div>';
$('.form_content').append(golden_site);
var lookup = '<input type="text" name="lookup" value="test">';
Why is this not working:
$(golden_site).append(lookup);
But accessing the node by id works:
$('#golden_site').append(lookup);
This $('#golden_site') selects the div with id=golden_site. While this $(golden_site) doesn't select anything.
Taken from here, you have the following ways of selecting an element using jQuery
Selecting Elements by ID
Selecting Elements by Class Name
Selecting Elements by Attribute
Selecting Elements by Compound CSS Selector
Pseudo-Selectors
The way you tried to select your div doesn't follow one of the above ways. Hence you didn't make it. While using the id you made it, since this is included in the above ways.
update
As Guffa pointed out (I didn't now it) in his comment,
The call $(golden_site) doesn't try to use the string as a selector at
all. It will create an elements from the HTML string, and actually
return that element
The code is working fine, but it doesn't do what you think.
The $(golden_site) part will create a new div element from the HTML code in the string. The lookup element will then be appended to that div. As the div is an element that you just created, it's not in the page and the lookup element that you appended to it isn't in the page either.
If you create the div element first and then append that to the page, instead of using a string in the append, then you have a reference to the div element:
var golden_site = '<div id="golden_site"></div>';
var element = $(golden_site);
$('.form_content').append(element);
Now you can append things to it:
element.append(lookup);
Because when you say
$(golden_site).append(lookup);
Actually you mean:
'<div id="golden_site"></div>'
In plain words, it's just a string, not a jQuery object that can be appended to. golden_site is just a string.
The reason is because the $() is in fact a wrapper of jQuery over the document.querySelector(). So as expected both methods should behave similar, when you do:
$("#blah").append(x);
Indeed the browser is doing this:
document.querySelector("#blah").appendChild(x);
So both methods should work as they explain here -> How query Selector works
As you can see the variable passed as argument is a string that will be used as a CSS Selector, they explain here -> CSS Selector List
I will add this graphic with some of the most common ways to select elements from the DOM, don't forget the '', courtesy from W3CSchools.
Similar to this thread, I am trying to be able to add and remove select boxes for different parts of my document. However, when I call the remove function, it removes the first instance of my cloned object, instead of the last. I have tried using :last and :last-child, but they do not seem to be working(May just be a syntax error, as I am new to Javascript/Jquery)
Also, should I be assigning different id's to each of my cloned objects? My goal is for each g:select to select a database object, and compile all of the different objects text into 1 big string (each object has a 'documentBody' field that I want to compile). Since I am basically doing the same thing to each object, is it necessary for me to assign specific id's to each select, or will just cloning them be sufficient?
Here is what I currently have implemented
<div id="selects">
<g:select name="intro"
id= "intro" from="${package.name.Subtag.findAllWhere(tag: package.name.Tag.get(2))}" noSelection="['': 'Please choose Subtag']"/>
</div>
<button onclick="addSelect()">Add</button>
<button onclick="removeSelect(intro)">Remove</button>
and
<g:javascript library="jquery"/>
<g:javascript>
function addSelect(){
var cloner = $("#intro").clone();
$("#selects").append(cloner);
}
function removeSelect(id){
$("#intro:last-child").remove();
}
</g:javascript>
As Jai has mentioned, the issue is that you are cloning and appending an element with an id, creating a duplicate id on the page. When jQuery searches for an element by id, it stops at the first one found, regardless of any other pseudo classes.
The issue is that a duplicate id on the page means that the HTML document is invalid, so all bets are off. Older browsers may even throw an error. Using a class rather than an id prevents the .clone() function from copying the dupe id, but if you still need the first element's id, you can always remove it from your cloned object before appending it to the page:
cloner.removeAttr('id');
I trying to clone a div content with below code.
var clonedItem = $("#cloneableSchoolTab").clone();
clonedItem.find(".clonableSchool").addClass("clonedSchoolTab" + schoolTabCount );
$("#clonedSchoolTabsContainer").append(clonedItem);
First line gets the whole target item. But, the excecution of second line, the value of clonedItem changed as empty array. I dont know. If i merge the first 2 line, the reasult was same as the above code.
HTML Code:
<div id="cloneableSchoolTab" class="schoolInput">
<input type="text" id="schName"/>
<input type="text" id="schDes"/>
</div>
Any help would be appreciative.
Thanks in advance
Can you post some HTML code, so that we can see what are the elements the above code is trying to clone, the only thing that I can see is if the find() method fails to find an element with class name ".clonableSchool" then it is constructing an empty jQuery object, as the jQuery doc says:
the .find() method allows us to search
through the descendants of these
elements in the DOM tree and construct
a new jQuery object from the matching
elements
Note: I believe it should be a comment not an answer, but I don't have that privilege yet, sorry.