Changing name attr of cloned input element in jQuery doesn't work in IE6/7

两盒软妹~` 提交于 2020-01-19 05:38:06

问题


This SSCCE says it all:

<!doctype html>
<html lang="en">
    <head>
        <title>Test</title>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
                $('#add').click(function() {
                    var ul = $('#ul');
                    var liclone = ul.find('li:last').clone(true);
                    var input = liclone.find('input');
                    input.attr('name', input.attr('name').replace(/(foo\[)(\d+)(\])/, function(f, p1, p2, p3) {
                        return p1 + (parseInt(p2) + 1) + p3;
                    }));
                    liclone.appendTo(ul);
                    $('#showsource').text(ul.html());
                });
            });
        </script>
    </head>
    <body>
        <ul id="ul">
            <li><input type="text" name="foo[0]"></li>
        </ul>
        <button id="add">Add</button>
        <pre id="showsource"></pre>
    </body>
</html>

Copy'n'paste'n'run it, click the Add button several times. On every click you should see the HTML code of the <ul> to show up in the <pre id="showsource"> and the expected code should roughly be:

<li><input name="foo[0]" type="text"></li>
<li><input name="foo[1]" type="text"></li>
<li><input name="foo[2]" type="text"></li>
<li><input name="foo[3]" type="text"></li>

This works as expected in FF, Chrome, Safari, Opera and IE8.

However, IE6/7 fails in changing the name attribute and produces like:

<li><input name="foo[0]" type="text">
<li><input name="foo[0]" type="text">
<li><input name="foo[0]" type="text">
<li><input name="foo[0]" type="text"></li>

I googled a bit and found this very similar problem, he fixed it and posted a code snippet how it should have look like. Unfortunately this is exactly what I already have done, so I suspect that he was only testing in IE8, not in IE6/7. Other than that particular topic Google didn't reveal much.

Any insights? Or do I really have to grab back to document.createElement?

Note: I know that I can use just the same name for each input element and retrieve them as an array, but the above is just a basic example, in real I really need to have the name attribute changed, because it not only contains the index, but also other information such as parentindex, ordering, etc. It's been used to add/rearrange/remove (sub)menu items.

Edit: this is related to this bug, The jQuery (I'm using 1.3.2) does thus not seem to create inputs that way? The following does just work:

$('#add').click(function() {
    var ul = $('#ul');
    var liclone = ul.find('li:last').clone(true);
    var oldinput = liclone.find('input');
    var name = oldinput.attr('name').replace(/(foo\[)(\d+)(\])/, function(f, p1, p2, p3) {
        return p1 + (parseInt(p2) + 1) + p3;
    });
    var newinput = $('<input name="' + name + '">');
    oldinput.replaceWith(newinput);
    liclone.appendTo(ul);
    $('#showsource').text(ul.html());
});

But I can't imagine that I am the only one who encountered this problem with jQuery. Even a simple $('<input>').attr('name', 'foo') doesn't work in IE6/7. Isn't jQuery as being a crossbrowser library supposed to cover this particular issue under the hoods?


回答1:


Here is a function that will set the name of an element in all browsers, even IE6 and IE7. It is adapted from the code at http://matts411.com/post/setting_the_name_attribute_in_ie_dom.

function setElementName(elems, name) {
  if ($.browser.msie === true){
    $(elems).each(function() {
      this.mergeAttributes(document.createElement("<input name='" + name + "'/>"), false);
    });
  } else {
    $(elems).attr('name', name);
  }
}

I found that using replaceElement and outerHTML was not reliable across different versions of IE. But the mergeAttributes trick above works perfectly!




回答2:


I created a partial solution for this issue, which I describe here: http://www.danconnor.com/dynamic-name-input-attributes-with-ie-and-jquery-clones.html

Basically:

$(some_cloned_element).each(function(i, elem){
    var newName = "yay_i_love_my_new_name";
    if ($.browser.msie === true){ // evil browser sniffing *cries*
        $(elem).replaceWith(document.createElement(
            this.outerHTML.replace(/name=\w+/ig, 'name='+newName+'_'+i)
        ));
    } else {
        $(elem).attr('name',newName+'_'+i);
    }
    $("body").append(some_cloned_element);
});

Definitely sucks but definitely works.




回答3:


I wonder if you are running into this bug in IE (even with jQuery)?

Essentially in IE you can't change the name attribute of elements (regular or cloned) (and then re-access them via javascript by name) although you can submit them (e.g. input elements) and have them successfully submit.




回答4:


not an answer, is an analysis to the question asked:

<!doctype html>
<html lang="en">
    <head>
        <title>Test</title>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
                $('#add').click(function() {
                    var ul = $('#ul');

                    var liclone1 = ul.find('li:last').clone(true);
                    var liclone2 = ul.find('li:last')[0].cloneNode(true);
                    var liclone3 = $( ul.find('li:last')[0].cloneNode(true) );
                    var liclone4 = $( '<li><input type="text" name="foo[88]"></li>' );

                    var linew    = document.createElement("li"); 
                    linew.innerHTML = '<input type="text" name="foo[99]">';

                    $('#showsource').text("");
                    $('#showsource').text($('#showsource').text() + $(liclone1)[0].outerHTML);
                    $('#showsource').text($('#showsource').text() + $(liclone2)[0].outerHTML);
                    $('#showsource').text($('#showsource').text() + $(liclone3)[0].outerHTML);
                    $('#showsource').text($('#showsource').text() + $(liclone4)[0].outerHTML);
                    $('#showsource').text($('#showsource').text() + $(linew)[0].outerHTML);
                    $('#showsource').text($('#showsource').text() + $(ul)[0].outerHTML);
                    $('#showsource').text($('#showsource').text() + $(ul)[0].innerHTML);

                });
            });
        </script>
    </head>
    <body>
        <ul id="ul">
            <li><input type="text" name="foo[0]"></li>
            <li><input type="text" name="foo[1]"></li>
        </ul>
        <button id="add">Add</button>
        <pre id="showsource"></pre>
    </body>
</html>

Result:

<LI><INPUT name=foo[1]> 
<LI><INPUT name=foo[1]> 
<LI><INPUT name=foo[1]> 
<LI><INPUT name=foo[88]></LI>
<LI><INPUT name=foo[99]></LI>
<UL id=ul><LI><INPUT name=foo[0]> 

<LI><INPUT name=foo[1]> </LI></UL><LI><INPUT name=foo[0]> 
<LI><INPUT name=foo[1]> </LI>

so I can analyze it, the only way is to make a new li with createElement or create the object with $(...)




回答5:


This post is also about this subject which gave me an insight into this problem.

Weird behaviour of iframe `name` attribute set by jQuery in IE




回答6:


i know this is old, but since i didnt really find anything that worked for me i made a pretty simple solution, though, an ugly one:

convert html to text using jquery, then use js string functions to do as you want with it and insert the string as html using jquery.

just for anyone who still comes across this, like myself :)



来源:https://stackoverflow.com/questions/2094618/changing-name-attr-of-cloned-input-element-in-jquery-doesnt-work-in-ie6-7

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!