Изменение имени атрибута клонированного элемента ввода в jQuery не работает в IE6 / 7 - PullRequest
22 голосов
/ 19 января 2010

Это SSCCE говорит само за себя:

<code><!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">

Скопируйте и запустите его, нажмите кнопку Add несколько раз. При каждом нажатии вы должны увидеть HTML-код <ul>, который будет отображаться в <pre id="showsource">, и ожидаемый код должен быть примерно равен:

<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>

Это работает, как и ожидалось, в FF, Chrome, Safari, Opera и IE8.

Однако IE6 / 7 не может изменить атрибут name и выдает следующее:

<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>

Я немного погуглил и обнаружил эту очень похожую проблему , он исправил ее и выложил фрагмент кода, как это должно выглядеть. К сожалению, это именно то, что я уже сделал, поэтому я подозреваю, что он тестировал только в IE8, а не в IE6 / 7. За исключением этой конкретной темы, Google мало что раскрыл.

Есть идеи? Или мне действительно нужно вернуться к document.createElement?

Примечание: я знаю, что могу использовать одно и то же имя для каждого элемента ввода и извлекать их в виде массива, но приведенное выше является лишь базовым примером, в действительности мне действительно нужно изменить атрибут имени, потому что он содержит не только индекс, но и другую информацию, такую ​​как parentindex, порядок и т. д. Он используется для добавления / перестановки / удаления (под) пунктов меню.

Редактировать: это связано с этой ошибкой , JQuery (я использую 1.3.2), таким образом, похоже, не создает входные данные таким образом? Следующее действительно работает:

$('#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());
});

Но я не могу себе представить, что я единственный, кто столкнулся с этой проблемой с jQuery. Даже простой $('<input>').attr('name', 'foo') не работает в IE6 / 7. Разве jQuery не является кроссбраузерной библиотекой, предназначенной для решения этой конкретной проблемы?

Ответы [ 6 ]

9 голосов
/ 05 мая 2011

Вот функция, которая будет устанавливать имя элемента во всех браузерах, даже в IE6 и IE7. Адаптировано из кода на 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);
  }
}

Я обнаружил, что использование replaceElement и outerHTML не было надежным в разных версиях IE. Но вышеприведенный трюк слияния атрибутов работает отлично!

4 голосов
/ 06 ноября 2010

Я создал частичное решение для этой проблемы, которое я опишу здесь: http://www.danconnor.com/dynamic-name-input-attributes-with-ie-and-jquery-clones.html

В основном:

$(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);
});

Определенно отстой, но определенно работает.

3 голосов
/ 18 марта 2010

Интересно, сталкиваешься ли ты с этой ошибкой в ​​IE (даже с jQuery)?

По сути, в IE вы не можете изменить атрибут имени элементов (обычный или клонированный) (а затем повторно получить к ним доступ через javascript по имени), хотя вы можете отправить их (например, элементы ввода) и успешно их отправить. 1007 *

2 голосов
/ 19 марта 2010

Этот пост также посвящен этой теме, которая дала мне понимание этой проблемы.

Странное поведение атрибута iframe `name`, установленного jQuery в IE

2 голосов
/ 19 января 2010

не ответ, это анализ заданного вопроса:

<code><!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">

Результат:

<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>

так что я могупроанализируйте его, единственный способ - создать новый li с помощью createElement или создать объект с помощью $ (...)

1 голос
/ 15 февраля 2011

я знаю, что это старо, но так как я действительно не нашел ничего подходящего для меня, я сделал довольно простое решение, хотя и уродливое:

конвертировать HTML в текст с помощью jquery, затем используйте строковые функции js, чтобы сделать с ним все, что вы хотите и вставьте строку как HTML, используя jquery.

только для тех, кто все еще сталкивается с этим, как я:)

...