admin管理员组

文章数量:1418345

I'm having problems with my application due the ID collision. The application basically uses AJAX to load code snippets on user demand. These snippets are very different, but sometimes, a code snippet uses the same ID than another in a HTML tag.

Imagine user asks for snippet 1 and gets this:

....
<input id="myvar" type="checkbox" name="myname" />
....

This snippet is added to the main page code through JQuery.load()

Then, user ask for snippet 2 and gets:

....
<div id="myvar">....</div>
....

At this moment, there are 2 different HTML tags with the same ID, so when the app does:

$("#myvar").something()

the result is undefined.

So, the problem is I don't know if it's possible to split code snippets in HTML using any javascript or HTML feature or trick.

It's not an option to prefix all ID on load, due each snippet has an associated javascript code to process it and needs to have access to the snippet DOM.

Good news: snippets are pletly isolated on the page. The page structure is like this:

<html>
  <head>...</head>
  <body>
    <div id="header">...</div>
    <div id="mon_controls">...</div>
    <div id="snippets">
      <div class="snippet" id="snippet-1">
        // Snippet 1 code here
      </div>
      <div class="snippet" id="snippet-2">
        // Snippet 2 code here
      </div>
    </div>
  </body>
</html>

Any idea?

Edit: I can't control snippets content, so it's not an option force to use specific ID names.

I'm having problems with my application due the ID collision. The application basically uses AJAX to load code snippets on user demand. These snippets are very different, but sometimes, a code snippet uses the same ID than another in a HTML tag.

Imagine user asks for snippet 1 and gets this:

....
<input id="myvar" type="checkbox" name="myname" />
....

This snippet is added to the main page code through JQuery.load()

Then, user ask for snippet 2 and gets:

....
<div id="myvar">....</div>
....

At this moment, there are 2 different HTML tags with the same ID, so when the app does:

$("#myvar").something()

the result is undefined.

So, the problem is I don't know if it's possible to split code snippets in HTML using any javascript or HTML feature or trick.

It's not an option to prefix all ID on load, due each snippet has an associated javascript code to process it and needs to have access to the snippet DOM.

Good news: snippets are pletly isolated on the page. The page structure is like this:

<html>
  <head>...</head>
  <body>
    <div id="header">...</div>
    <div id="mon_controls">...</div>
    <div id="snippets">
      <div class="snippet" id="snippet-1">
        // Snippet 1 code here
      </div>
      <div class="snippet" id="snippet-2">
        // Snippet 2 code here
      </div>
    </div>
  </body>
</html>

Any idea?

Edit: I can't control snippets content, so it's not an option force to use specific ID names.

Share Improve this question asked Sep 27, 2011 at 16:44 IvanIvan 16k18 gold badges64 silver badges99 bronze badges 7
  • 4 All IDs need to be unique; that's the bottom line. This is something that should and could be managed server-side - you don't mention a framework, but I assume this isn't just a flat file HTML page? – Widor Commented Sep 27, 2011 at 16:50
  • As @Widor says, the ids must be unique. – Eric Commented Sep 27, 2011 at 16:53
  • Yes, that's the problem. I cannot manage non-unique IDs and it's not a good practice, but I cannot force user's to do it and, also if I do, some user could make a mistake. The problem on the server side is that I can modify HTML snippet, but not its corresponding javascript snippet, so if I change an ID this javascript snippet will not find the DOM items it needs. – Ivan Commented Sep 27, 2011 at 17:00
  • Could you not traverse the DOM without using IDs, instead referring to this when handling events and making use of jQuery's selectors and Parent/Child/Sibling to select the correct nodes on which to act? As you must be returning AJAX from the server, can it not wrap the response in a containing element as a reference from which you can locate what you need? – Widor Commented Sep 27, 2011 at 17:05
  • 1 Do you control the JS that needs access to those snippets? Change the IDs that those code blocks are using, then massage the colliding snippets to change IDs BEFORE inserting the snippets into the DOM. – Marc B Commented Sep 27, 2011 at 17:11
 |  Show 2 more ments

3 Answers 3

Reset to default 4

It is considered invalid in HTML to have the same ID multiple times, and as you've seen it can cause issues.

If you have control over the output of the Ajax code, the best solution would be to prevent it from outputting the same ID multiple times. You haven't given enough information to allow me to give you much help with exactly how to achieve this, but it should certainly be possible.

If the same IDs are ing from different Ajax calls, you could ensure that all IDs produced by each Ajax call are prefixed by a unique name (possibly the module name of the piece of code producing them?).

If they're ing from the same code, the only reason you should be likely to produce the same ID is if you're outputting the same piece of data multiple times onto the page. Even here there will be solutions to this, but I would need to know more about the application to help much in this case.

But in either case, the problem as described seems to be with accessing it via jQuery. The good news is that jQuery is actually very forgiving of duplicated IDs.

If it's just a case of getting it to work with jQuery, then you should be able to get it working without having to fix the actual duplication. As long as you can run a selector that picks the one you want uniquely, then jQuery will be quite happy.

If you want to do this, simply wrap each Ajax response in a <div> with a unique ID of its own, and then you can reference the two duplicates using a nested selector as follows:

$("#ajaxblock1 #myvar").something()
$("#ajaxblock2 #myvar").something()

This will work just fine in jQuery.

I can't vouch for the same thing working well in CSS, however, and the standard DOM getElementById() function will also freak out, so if you plan to use anything other than jQuery, then you will want to de-dup your IDs.

The best solution is to embed each code snippet in a separate IFRAME, because the ID may not be the only conflict-causing item.

  • Snippets that heavily rely on the document's default CSS/script attributes may fail due conflicting scripts.
  • Script snippets that throw variables in the global scope may interfere with the other snippets
  • Script snippets that refer to a specific class index (class="specific") will also break due conflicts
  • Snippets containing <script> will not be executed when inserted in the HTML, while it may be important for the appearance of the snippet.

Et cetera. Just embed the snippets in a scripted iframe to circumvent these possible issues.

EDIT
Frames can easily municate with the parent (even cross-domain) through postMessage. When you're in the same domain, municating is even easier.

You're probably looking for an easier method to municate between child frames. Well, consider this example (same domain only):

JS:

//Snippet from frame 1
var othersnippet = parent.frames["othersnippet"].contentWindow;
othersnippet.getspecialMethod(); //Custom function, EXAMPLE
  • parent (within the frame) = top, which refers to the Window object
  • window.frames is an object which refers to all frames within one document, by name. Note: "Within a document" doen't include the frames in frames)

HTML:

<iframe name="othersnippet" />
<!-- No id needed, because you access frames through the
     window.frames[name] property-->

Just a thought:

If you know that the snippets will always be above (or below) the duplicate content #id, you might be able to do something like this:

if ($('#myvar').length == 1) {run function} //no offending repeat #id
else {$('#myvar').eq(1) . . . } //repeating #id, refer to the second instance

本文标签: javascriptSeparate quotnamespacesquot in HTMLStack Overflow