JQuery basic selector usage and non unique element

2019-02-27 11:18发布

问题:

I'am maintaining a GUI built using JQuery. In one part of the GUI, multiple tabs can be opened to edit data.

When a new tab is opened, it is created by cloning the first tab content div and updating the input fields in the div.

The new tab is given a unique ID based on the tab index, but all other ID's within the cloned tab div are the same as the original tab div.

Now, that seems to cause problems since ID's are not unique any more. When selecting an input field the following works on Firefox 3.6.8:

$('#tabs-2 #scriptName').val( data.name );

This selects the tab div with ID tabs-2 and then selects the input field within that div with the ID scriptName and sets its value. Now this does not work on Chrome or Firefox 3.0.19.

The DOM hierachy looks something like this

<div id="tabs">
     <div id="tabs-1">
         ...
         <input id="scriptName"/>
         ...
     </div>
     ...
     <div id="tabs-2">
         ...
         <input id="scriptName"/>
         ...
     </div>
 </div>

One solution would be to make all ID's wihtin the cloned tab content div unique, but that seems like a brute force aproach. It must be possible to address the content within a div in a more independent way without require a unique ID.

The cloning of the whole div when generating a new tab is of course a crude hack, a more elegant solution would be to reuse the same div but change the content depending on the selected tab, but that is how it is built right now and unfortunately it was developed and tested using a later firefox browser where this selector worked.

Pre-post EDIT

I found a lot of related questions with answers that gave some hints on how to solve this, when I inserted my offline-edited question, but I post this question anyway since good suggestions for how to solve this are always welcome.

EDIT

I'am trying the class approach right now, I do have one problem though, some input fields uses labels with for attribute, the for attribute must point to a unique id. But that can be solved by omitting the for attribute and make the input field a nested element instead.

回答1:

ID's are unique identifiers. The moment you introduce a duplicate id, you have an invalid document on your hands.

The best way to get around this is to refrain from using id's on anything that is going to be cloned. Instead, use a "unique" class name to identify the element. Then, when it is cloned, you can walk down the DOM to each copy of the class. jQuery has very good DOM traversal methods for this.

http://api.jquery.com/category/traversing/

Additionally: .children(), .parent(), .parents(), and .siblings() are particularly useful. I'd stay away from .find() unless it cannot be helped. .find() can be slow if you are searching through many, many nodes in the DOM. Since you're building an interface, this might be the case.



回答2:

just a suggestion, can you make id of the input as class? So that you don't have a problem when cloning. and your code would be something like, $('#tabs-2 .scriptName').val( data.name );



回答3:

I don't know will it helps in your case but you can try .find() jQuery method.

Try something like this expression:

$('#tabs-2').find('#scriptName').val( data.name );


回答4:

I have a AngularJS app where I ran into the same problem when ng-repeating elements. Heres how I solved it.

Your tabs, the parent element, have unique ID's right? So just go down the children of that tab. Snipit from my div-windows to get children for resizable parent and alsoResize (or manualy resize as in my case) the children. Hint: I just left the IDs out of the children. $scope.panes[] is my window array, I just grab the ID and each out the children:

var objParent = $('#' + $scope.panes[index].windID); //entire div window
var objChild = [];
//objChild[0] = title bar
//objChild[1] = contentpane
objParent.children().each(function(i){
    objChild[i] = $(this);
});

Another solution would be to built the whole tab as a string and innerHTML it to the page. This way you can do someting like this with the ids: (again my div-window example)

child1ID = "id='"+windID+titlebar+"'";
child2ID = "id='"+windID+contentpane+"'";