Is there any proper way to reuse Id's? - javascript

I have a "create" form inside a bootstrap's modal. All my Javascript related with that form uses id's and not classes. Now what i want to do is to create a second form that uses the same Javascript (based on id's as said before). Is there any proper way to achieve that? I know that is a very bad practice to use dublicate id's.

No, there is no proper way to ever duplicate the use of id's. Browser behavior for this is a mixed bag and cannot be relied on.
Use classes instead or create dynamic id's for each form.

Not really, no.
When you use IDs, you're telling the browser that the ID is uniquely available, on the page.
If you have two forms with the same IDs, that means you've broken that guarantee.
An example of where this causes problems is document.getElementById( ).
It will grab the first element it finds.
If there are two, it will only get you the first one.
Another issue:
forms with IDs have a habit of being saved to Window, using that ID (this behaviour isn't 100% standard across every browser with more than 2% usage, globally, today, but it's still pretty common).
Ugly solutions I've seen in this space are things like "my-id-1" "my-id-2", et cetera, where you then access them like: document.getElementById("my-id-" + x);
...really not pretty at all...
...alternatively, you can keep the forms in JS, and just attach them to the page, when you want to switch back and forth.
In this way, they can share IDs, so long as they're never attached to the page at the same time.
document.querySelector("#my-form") === form1; // true
form1.parentNode.replaceChild(form2, form1);
document.querySelector("#my-form") === form2; // true
Again, this isn't going to help you with the built-in form and input namespacing, in any meaningful way, but if that's a feature you are 100% ignoring (not a bad thing to do), this will solve those problems.
Alternatively, you could just move to classes and data-attributes (or just attributes), and life would get easier still...

If you insist on using two forms on one 'page' and share ids between them, you have few options to make it work and be relatively 'clean' about it. Not knowing your technology stack, I can't give a completely relevant answer. However you can do something similar to the below:
HTML
<div id="myFormDiv"></div>
JAVASCRIPT
$("#myFormDiv").load(urlToForm);
You would naturally need your forms to be in separate html files for this to work as there is no way you can reliably use ids on multiple elements in one html file.

Related

Vanilla Javascript & Dom Performance

I've been learning Javascript online and have recently started to put it to use on a website. I'm still a little confused about what might be the most efficient/performant ways to do things, though. A few questions with that in mind...
If a webpage has multiple click events in different sections, each doing something different, one event listener in the body tag — with multiple if/else statements — would be the most efficient way to handle them all. Is that correct?
Is the search method a good way to handle if/else statements in this case? For example:
if (event.target.className.search("js-tab") !== -1) {
// do something
} else if (event.target.className.search("js-dropdown") !== -1) {
// do something else
}
The ID performance only applies to actually finding an element, right? There wouldn't be a difference between event.target.className.search and event.target.id.search, would there? (assuming there aren't an insane amount of class names to search through on that element). I'm currently using className for sections that have the same functionality (multiple tabbed sections on the same page, for example). I suppose I could just as easily use the or operator if it made a difference, like so:
if ((event.target.id.search("js-tab-one") !== -1) || (event.target.id.search("js-tab-two") !== -1))
When there are multiple elements that a click event could potentially be on (an icon inside of an anchor link, for example), how much of a performance hit is it to add additional if/else statements (i.e. check the tag type, and if it's not the a tag, move up)? I recently refactored my css so that my icons were set to width: 100% and height: 100% (ensuring that the click was always happening on the same element every time), but I wonder how much of a performance boost (if any at all) I actually got by doing this?
If a webpage has multiple click events in different sections, each
doing something different, one event listener in the body tag — with
multiple if/else statements — would be the most efficient way to
handle them all. Is that correct?
No. It's useful for handling events on elements that you add dynamically, but not so much for regular events.
Handling all the events in the body means that you will handle all the events. Every click that happens goes through your code to see if it comes from one of the elements that you are interested in.
Is the search method a good way to handle if/else statements in this
case?
No. The search method uses a regular expression, not a string, so the string will be parsed to create a RegExp object. Then a search is done using the regular expression, which is slower than a normal string search, and can give unexpected results.
To look for a string in another string you should use the indexOf method instead. You should however be aware that it will look for a match anywhere in the string, not matching whole class names. It will for example find "all-head" when the element has the class "small-header".
The ID performance only applies to actually finding an element, right?
Yes.
When there are multiple elements that a click event could potentially
be on (an icon inside of an anchor link, for example), how much of a
performance hit is it to add additional if/else statements (i.e. check
the tag type, and if it's not the a tag, move up)?
That means that every click event will have to go through the extra if statements.
If you bind the event to the element instead, you know that the event happened inside that element and you don't have to know which element did actually catch it.
A lot of what you're asking is subjective though and it fits in the context that is trying to happen. So there might be a reason why the below might be not good (as another commenter said, don't prematurely optimize). But there are some programming techniques that can be said about what you have done, namely modularity. There's a few performance considerations but they mostly revolve around writing good code:
1) it really depends on your handler, if you intend to delete and add DOM elements, this can be better because you watch the document instead of tying in a new click handler to each element. but this can be bad because its not modular if you have it do too much stuff. But if its just looking at the state, then this is not really good performance wise....
2) i wouldn't say that the search has any impact on the if else's, but in considering optimization of this particular situation you describe later on, I wouldn't do that. As each time you go through each if-else you end up doing another search and it can add up in the long run if you have a lot of if-elses in the way.
3) there shouldn't be a difference but why search in an id string? unless your id string is part of some unholy long part like musical-js-tab-one-musical-tab which I wouldn't suggest to use as an id like this anyway, you should split it up, you shouldn't tie functionality like that, use classes instead like class='musical' id='js-tab-one' since id's should describe a singular object on the page.
4) everytime you add an if-else, no matter how small it is, is another computer cycle and a little bit more memory. and it can add up, just attach your click handler by tag and by class at this point and let the browser decide to optimize it.

what happens if one set id attribute values of several html tags, the same string?

I recently saw a html page, that i thought the id of several html tags was the same, then I realized the ids are unique but it raises the question that what could have happened if the page actually used several tags
As i have heard id attribute of every html tag(if it has one) must be unique,
now i wonder what happens if it is not the case??
what possible errors can it cause?
does different browsers show different reactions for this issue?
does javascript and jquery codes that use duplicated ids run on both tags or what?
Duplicate ids can have various different effects. Which you experience will depend on the method you use to try to access them (and possibly also from browser to browser).
You'll affect all of them
You'll affect the first one
You'll affect the last one
You'll get a collection instead of an element, try to treat it like an element and get an error
Duplicate ids are not allowed in HTML. Don't make trouble for yourself. Use classes for groups and ids for unique identifiers.
Change them as soon as possible, to save a lot of headache in the future. For elements with same property use classes
About your queries,
Now i wonder what happens if it is not the case??
Well, the HTML is not a valid one anymore. Now a days it doesn't hurt much but still not preferred.
What possible errors can it cause?
Errors are little bit hard to predict. But with jQuery you are going to get many.
Does different browsers show different reactions for this issue?
Not sure.
Does javascript and jquery codes that use duplicated ids run on both tags or what?
jQuery will give you trouble. Consider a case where you have two input fields with same ID.
and you try to select second one with out noticing. jQuery('yourID').val() and you'll be selecting the firs value instead. Like this there are a lot of possibilities.
As you said, HTML id, per specs, must be unique. If one where to put duplicated id, the js behavior relative to those ids will be unpredicatable, and could even change between 2 calls.
Any js call on one id (jquery or not) will point to one of the id but without guarentee that :
It will be the same every call
It will have the same order between 2 page refresh
It will have the same behavior beween 2 different browser
It will have the same behavior betwween 2 time the same browser
The problems that could emerge depend on how toghtly the js code is coupled to the underlying element DOM structure anw could mostly point to a undefined exception and stop the js execution.

How should I avoid duplicate IDs when writing JS-heavy web apps?

Specifically, I have areas of my (heavily JS) web page that contain lists of HTML elements and for simplicity let's assume there are just two lists: A and B. Let's also say When I click on the first item in list A (A1) something happens to the first item in list B (B1).
I gave each element in list A a common HTML class and an ID (like <li class='listAmember' id='1'>...</li>). I set up elements in list B in a similar way (like <li class='listBmember' id='1'>). Then I attached some click handlers (using jQuery in this case) and ran into problems with duplicate IDs, even if I qualified my jQuery id-based selectors with the class name, like this
$('.listAmember#1').click(function(){});
I've realised that this is bad practice (IDs are supposed to be unique in the document!) but I'm unsure what good alternatives there are.
I don't really want to create IDs like listAmember-1 because if I have, say, a lookup-table in my JS code that is keyed on the numeric ID, I'd need to parse out the 1 from that ID string to get the 'real' ID. (And I would still need to add a class like listAmember for styling purposes and that seems unnecessarily repetitious?) All in all that seems clumsy and I assume there are better ways?
As Florent says, I would try and avoid IDs altogether. One convention is to use class names like js-list-a to signify it's a class intended for JavaScript usage only. Then you're free to start using the index of the li within the list.
Also, you could just set one click handler on the list and use event delegation .
A combination of these ideas means you won't have to touch IDs.
For Unified ID's maybe in a System that has external Libarys in use, you should always attach them with a Namespace. For Example like: "myFancySlider-container"
This helps to keep names Unique for your special application.
If you generate Dynamic Code, you have to Make sure, to only create One of each object. Or you Assemble them With iterations. An alternative to that, could be the unifying with Timestamps.
EDIT
As others already mentioned, you should avoid Using ID's as you can. ID's only make sense, to benefit from the Unique Attributes. For example, you know exactly what element you want, so an ID can be a verry good shortcut for that. Specialy in dynamic Content Applications.

To what extent should I enforce a DOM element's ID's uniqueness?

I'm experiencing an issue which has two possible solutions. I am unsure which solution is 'more correct.'
I have a modal dialog which opens above a page. This dialog hosts an element with ID "foo".
Now, that is not an issue at all on its own. However, the non-dialog page has multiple tabs. One of these other tabs, deep down in some content, also has an ID "foo." This causes weird, intermittent issues depending on which "foo" is encountered first when traversing the DOM tree.
Unfortunately, both values are presenting exactly the same information in exactly the same way. The only difference is that one is being hosted inside of a dialog. The same model is being used -- thus the same ID is being generated by my ViewModel.
I can do one of two things:
Explicitly override one of these ID-creation methods to ensure that the ID generated in the dialog is unique when compared to that of the non-dialog.
Modify my jQuery search selector to only read from the dialog's form inward -- ensuring that the dialog will not capture unexpected DOM elements.
It would seem like the second idea is a better practice. I traverse less DOM nodes and don't have to hack anything in. However, to an unknowing developer, one could still accidentally re-introduce this issue by not starting searching from the proper area.
The same issue could be said to any developer working on our application, though. They would need to know explicitly to override the ID-creation of the ViewModel such that it does not create the same ID.
Is it ever acceptable to have repeating IDs if they're encapsulated in different forms? Where does the expectation of an ID being unique cease to make sense?
The ID is generated through MVC's EditorFor HTML Helper. I can override this in such a way that it generates a form-specific ID, but that was clearly not MVC's intention.
<%= Html.EditorFor(model => model.CustomerDisplayName) %>
UPDATE: It appears I should be enforcing the IDs uniqueness. However, ASP.NET MVC3 does not seem to provide an easy way of ensuring an ID is unique to the DOM. I can append on the form's ID, but that would generate huge IDs.. not sure if that is the best call. Any thoughts?
Is it ever acceptable to have repeating IDs if they're encapsulated in
different forms?
It is never acceptable, an ID should be unique. Otherwise your document is not valid.
Where does the expectation of an ID being unique cease to make sense?
The expectation of an ID being unique never ceases to make sense. It's part of the specs to have an unique ID per element.
Do you have control over the IDs? If you do, perhaps ID isn't the most "proper" way to go about it. If you used a class instead, then:
$("#DialogID .foo")
would select it without the potential for foo being a duplicated ID. The above selector will restrict the search to within the specified dialog.
To your question "To what extent should I enforce a DOM element's ID's uniqueness?", I boldly answer "You should NOT enforce unique IDs".
"Blasphemy!", I hear the Pharisees shout, vigorously waving the W3C bible.
But I live in the real world.
1. It is impossible.
It is virtually impossible to create a large website that guarantees the uniqueness of IDs.
Modern website are assembled from unrelated components, be it plug-ins, ads, widgets, you name it. All using their own set of IDs without knowing the existence of the other IDs on the page.
Technically the unique IDs can only be enforced by using some sort of GUID.
Of course, you could qualify, prefix or suffix your IDs with a classname or parent id and turn it into a long hierarchical composed ID. In fact this isn't that bad of a practice.
But there will be no guarantee. Bottom line.
2. It's not your fault.
Repeat after me: "It's not my fault...it's not my fault...".
I find it intellectually lazy and frustrating that the W3C team keeps this all too simplistic dogma alive, without looking at the real world. Do they suggest how to enforce this rule? Of course not - it's not their job. They only write the specs. But, if no one abides the law, either all of us are evil and doomed...or the law itself is at fault.
So, once again, repeat after me: "It's not my fault...it's not my fault...".
3. A bit of creativity, perhaps?
Is there really no way to adjust that rigid rule and come up with a practical solution? Either in the specs or implemented in the browsers? A form of "id scope"? A namespace?
4. Darwin says "To survive, you need to adapt."
The only way to survive in the real world is to adapt to the real world, with all it's imperfections. Some survival advice (as suggested by others already):
The more unique you make your IDs, the less chance for errors.
When searching for IDs, assume that there may be duplicates on your page. So, limit your search as much as possible.
Now stone me, I dare you.
You should enforce ID uniqueness 100%
The DOM requires that IDs be unique within it, else it is not valid, and as you've discovered you get strange and sometimes intermittent errors if you violate that requirement.
You can introduce some way to change the ID based on context, as you've mentioned, or you could take the approach of combining classes so you have, for example <div class="main foo"> and <div class="dialog foo"> where you can then use selectors to find "div.main.foo" or "div.dialog.foo" -- or get both by using just "div.foo"

selectors for action elements: class vs custom HTML5 attribute

A kinda of subjective issue I think. I have an action element and want to refer to it in the code for binding event I'm trying to choose between to ways of declaring such things:
1) the first option is more simple and straightforward in declaring and use:
<a class="play">Play</a>
('#menu .play').bind('click',...)
2) but the second option shows explicitly the purpose of the attribute
<a data-action="play">Play</a>
('#menu [data-action="play"]').bind('click',...)
Which should I choose (I'm not going to use selectors in CSS, only in JS code)?
If you're not using it for styles, I'd lean towards data-action="play" because it better describes the purpose (the action is play).
However, if you are planning on getting multiple elements like this and looping over them, I would either use class="play", because then you're treating them like a class of the same kind of thing again.. or use both, class for getting them and data-action to verify, can't go wrong there.

Categories