I'm working on creating a basic question app to better understand backbone marionette. I'm my free-text questions right now use the same "#question-number-range id for setting the range of numbers users can enter when taking a survey. Then I split up the range and assign the min/max values accordingly.
This works great for the first free-text question view. But when I try to do the same thing on a second it ends up getting set to the first's min/max values because they have the same id.
What I'm wondering - is there a way I can do something like $(#el < '#question-number-range') to target just the input within the current view's el, rather than any input that has that id?
Or am I completely going about this wrong and need to maybe dynamically create the ids?
An id attribute is:
A unique identifier for the element.
There must not be multiple elements in a document that have the same id value.
so if you have duplicate ids then you don't really have (valid) HTML and all sorts of strange things can happen.
A better approach is to use a class to identify elements of interest. Then you could use #$('.whatever-the-class-is') to find the element within your view's el:
$ (jQuery) view.$(selector)
If jQuery is included on the page, each view has a $ function that runs queries scoped within the view's element. If you use this scoped jQuery function, you don't have to use model ids as part of your query to pull out specific elements in a list, and can rely much more on HTML class attributes. It's equivalent to running: view.$el.find(selector)
so #$(x) is the same as #el.find(x) and will limit your search to the view.
Related
I have common jQuery function and two div tags. Both div tags have different names but both containing elements of identical ids now i want to use this common Jquery function for them both?
I have implemented common function but it's not working for both.
Here's link to my jsfiddle -jsfiddle.net/xS7zF/1/
In my jsfiddle there are two div tags namely example1 and example2 and both tags have elements of identical ids. Function is working fine for first div but not for second.
please help me to sort out this.
Yeah, under the hood, jQuery selection on an ID will use the Document.GetElementById() function implemented by the browser, which is really fast, but (i guess depending on the browser) will stop after it finds the first element, since ID's should be unique and no further searching is needed after the first one is found.
For instance, rename the divs with id="eb" to class="eb" and you can still target specific elements using $("#example1 .eb") and $("#example2 .eb")
UPDATE:
Using your new Fiddle I created this: http://jsfiddle.net/xS7zF/5/
I cleaned up a lot of code and hopefully you can see what I have done. I changed all elements that appear twice from id to class. Now, when you attach an event to an element using $(".classname").click(), it attaches to all the elements. In the handler function where you set HTML and do your show()/hide(), you don't target a specific element using it's ID, but you find it relative to the element that does the event. You can do this using parent(), parentsUntil(), next(), find(), etc. Check jQuery docs for all possibilities. So for instance, the change-handler attaches to all inputs with name=Assets. But instead of doing $("#b1").show(), I go to the parent of the specific input that fires using $(this).parent(). Then I find the element with a class=".b1", which it will only find the one that is next to this specific input and I set the HTML to just that element.
Since there is another input, the same actions happen when THAT input changes, but instead it finds IT's parent, and finds the element with class=".b1" that is next to IT. So both divs with input are contained since they act on elements relative to itself and not across the document.
For extra fun and to show you how flexible this way of programming is, here is a fiddle with the Javascript-code unchanged, but with the exact same question-div copied 8 times. No matter how many times you repeat this, the same code will act on as many divs as you create since everything works relative. http://jsfiddle.net/xS7zF/7/
Hopefully this helps, the rest is up to you!
ID's must be unique, you should not repeat them. You could replace id with class and in the jQuery function do (".ub").each() or manually referencing the object using eq(x). e.g. (".ub").eq(1).
You shouldn't assign same id's to different elements.
You CAN but you SHOULDN'T. Instead of giving the same id, use class
IDs must be unique, try fix this, change to classes.
You can try something like this:
$("div div:first-child")
instead of
$("#eb")
But depends of the rest of your page code. So, change to classes first and use
$(".eb")
when jQuery / javascript find the first ID it would ignore the rest, please read more about it
http://www.w3schools.com/tags/att_global_id.asp
I dont know good method how to get DOM element from template by javascript.
Example template:
<script id = "template" type="text/template">
<div>text1</div>
<div>text2</div>
<div>text3</div>
</script>
For example i want get div with "text2"
There is ways which i know, all of them are bad:
Add "class" to all elements - it breaks semantics (class created for CSS). In big projects you must use very long names for classes, its very inconvenient.
Get element by his number (index) - when adding a new element, you must rewrite old numbers in your code.
I see a couple of options:
If you don't want to use class , you can use a data-* attribute.
Assuming you load the template once and then duplicate its contents as desired, you could put id values on the elements in the template, which you then remove when cloning them and adding them to the document (so you don't end up with the same id on more than one copy of the element, which would be invalid and probably counterproductive).
Maybe you can also create as many templates as you need.
One for each div.
If you need to get each div at a time you must set ids to them ... of course you can also browse the dom inside script element to find the one you're interested in ...
Home this helps
Regards
mimiz
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 have an asp:bulletedlist control, which sits inside a div tag, and I need to count the number of list items inside the control. Searching the internet, and noting the fact the html given back by the items is a list i.e. <li>, I thought I could use an example of:
var listcontrol = document.getElementById('BulletedList1');
var countItems = listcontrol.getElementByTagName('li').length;
However, when I do this, it throws and error saying that no object exists for this control.
So, my problem is, and because I must do this clientside because I want to use this to set the height of the div tag, is how do you count the number of items inside a asp:bulletedlist control with javascript?
You can't use document.getElementById like you are using it because the actual ID for an Asp.Net control when rendered is different than what you set for the ID on the control. View the source of your page and you will see what the actual ID is. You can then use that if you want and this code should work, but it would break if you ever moved the bulletedlist control, since the hierarchy would change.
Another way to do this would be to use jQuery. In your example, you could do this:
$('[id$=BulletedList1]').children('li').size()
This would select the element that ends with 'BulletedList1', gets the li children, and then returns the size of the collection.
Here's what I'm trying to do: I have a bookmarklet that is looking for elements in the current page (which can be any site) and dispatch a click event on the ones that match. I have that part working.
In some cases though, nothing matches automatically and I want to be able to show (by hovering it) what element should be activated and then save some info about it in localStorage. The next time I'm using the bookmarklet on that page, I want to retrieve that info to identify the element in the DOM and then dispatch a click event.
The question is: what information should I save to be able to identify it? (in most cases, since it will always be possible to create a case where it doesn't work)
In the best case, said-element will have an id value and I'm good to go. In some other cases, it won't and I'd like to see your suggestions as to what info and what method I should use to get it back.
So far my idea is to save some of the element's properties and traverse the DOM to find elements that match everything. Not all properties will work (e.g. clientWidth will depend on the size of the browser) and not all types of elements will have all properties (e.g. a div node won't have a src value), which means that on one hand, I can't blindly save all properties, but on the other, I need to either choose a limited list of properties that will work for any kinds of element (at the risk of losing some useful info) or have different cases for different elements (which doesn't sound super great).
Things I was thinking I could use:
id of course
className, tagName would help, though className is likely to not be a clear match in some cases
innerHTML should work in a lot of cases if the content is text
src should work in most cases if the content is an image
the hierarchy of ancestors (but that can get messy)
...?
So, my question is a bit "how would you go about this?", not necessarily code.
Thanks!
You could do what #brendan said. You can also make up a jQuery-style selector string for each element in the DOM by figuring out the element's "index" in terms of its place in its parent's list of child nodes, and then building that up by walking up the DOM to the body tag.
What you'd end up with is something that looks like
body > :nth-child(3) > :nth-child(0) > :nth-child(4)
Of course if the DOM changes that won't work so good. You could add class names etc, but as you said yourself things like this are inherently fragile if you don't have a good "id" to start with, one that's put there at page creation time by whatever logic knows what's supposed to be in the page in the first place.
an approach would be using name, tagName and className-combination. innerHTML could may be too big.
another approach would be to look for child elements of your choosen element which have an id.
check for id => check for childs with id => check for name, tagName and className-combination (if => tell user to choose a different item :-)
What about finding all elements without an ID and assigning them a unique id. Then you could always use id.
What about using the index (integer) of the element within the DOM? You could loop through every element on page load and set a custom attribute to the index...
var els = document.getElementsByTagName("*");
for(var i = 0, l = els.length; i < l; i++) {
els[i].customIndex = i;
}