Изменение типа с помощью jQuery с кроссбраузерной поддержкой

#jquery #forms #dom #internet-explorer-8 #cross-browser

#jquery #формы #dom #internet-explorer-8 #кроссбраузерный

Вопрос:

Проблема

Следующие скрипты делают именно то, что мне требуется, во всех протестированных браузерах, кроме IE8, где кнопка удаляется, не заменяя ее чем-либо.

Предыстория

Я работал над методом замены входных данных типа отправки входными данными типа изображения с помощью jQuery.

Сначала у меня было следующее, которое работает с FF и webkit:

         marker = jQuery('<span class="marker"></span>').insertBefore('input#SearchButton');
        jQuery('input#SearchButton').detach().attr('type', 'image').attr('src',theme_folder '/style/images/search_button.png').insertAfter(marker);
        marker.remove();
  

Но это не удается во всех версиях 6 , если IE (кнопка удаляется, но не заменяется изображением), поэтому я разработал следующий скрипт для браузеров IE:

         marker = jQuery('<span class="marker"></span>').insertBefore('input#SearchButton');
        new_search = jQuery('<input id="SearchButton" value="Search" name="Searchbutton" type="image" src="' theme_folder '/style/images/search_button.png' '" />')

        jQuery(new_search).insertAfter('input#SearchButton');
        jQuery('input#SearchButton').remove();
        marker.remove();
  

Я использую условные обозначения HTML для фильтрации потока трафика в соответствующем скрипте, поэтому все это выглядит следующим образом:

 <!--[if IE]>
    <script>

        marker = jQuery('<span class="marker"></span>').insertBefore('input#SearchButton');
        new_search = jQuery('<input id="SearchButton" value="Search" name="Searchbutton" type="image" src="' theme_folder '/style/images/search_button.png' '" />')

        jQuery(new_search).insertAfter('input#SearchButton');
        jQuery('input#SearchButton').remove();
        marker.remove();

    </script>
<![endif]-->

<![if !IE]>
    <script>

        marker = jQuery('<span class="marker"></span>').insertBefore('input#SearchButton');
        jQuery('input#SearchButton').detach().attr('type', 'image').attr('src',theme_folder '/style/images/search_button.png').insertAfter(marker);
        marker.remove();

    </script>
<![endif]>
  

Ответ №1:

В IE type свойством input элемента является однократная запись. Вы не сможете изменить его после того, как вы установили его в первый раз. (В attr документации есть предупреждение об этом.)

Ваш единственный реальный вариант обеспечения совместимости с IE — это фактически заменить элемент на новый с тем же id значением. Очевидно, что это влияет на обработчики событий (любые, которые вы прикрепили к старому элементу, не будут прикреплены к новому), поэтому вы можете захотеть использовать delegate (или глобальную версию, live ) вместо того, чтобы прикреплять обработчики непосредственно к рассматриваемому элементу.

Обновить: А, я вижу, вы написали какой-то код для этого. Проблема с этим кодом заключается в том, что вы временно создаете недопустимый документ (в нем есть два разных элемента с одинаковым id значением), а затем ищете элемент по этому дубликату id . Будет хорошо, если вы просто возьмете элемент заранее:

 // Get the old search button
old_search = jQuery('input#SearchButton');

// Create the new search button
new_search = jQuery('<input id="SearchButton" value="Search" name="Searchbutton" type="image" src="' theme_folder '/style/images/search_button.png' '" />')

// Insert the new one after the old (temporarily creates an invalid document)
jQuery(new_search).insertAfter(old_search);

// Now remove the old one
old_search.remove();
  

(Для этого вам не нужен маркер, поэтому я удалил его из приведенного выше.)

Но вы можете вместо этого рассмотреть использование replaceWith :

 jQuery('input#SearchButton').replaceWith(
    '<input id="SearchButton" value="Search" name="Searchbutton" type="image" src="' theme_folder '/style/images/search_button.png' '" />'
);
  

Вот упрощенный replaceWith пример (также демонстрирующий delegate ):

HTML:

 <div id='container'>
  <p>This button is in the container, and so clicks
    on it will convert it back and forth between
    <code>input type='button'</code> and
    <code>input type='image'</code>.</p>
  <input type='button' value='Click Me'>
</div>
<div>
  <p>This button is <strong>not</strong> in the
    container, and so clicks on it aren't processed.</p>
  <input type='button' value='Click Me'>
</div>
  

JavaScript:

 $('#container').delegate('input', 'click', function() {
  if (this.type === "button") {
    $(this).replaceWith(
      "<input type='image' src='"   imageSrc   "'>"
    );
  }
  else {
    $(this).replaceWith(
      "<input type='button' value='Click Me'>"
    );
  }
});
  

Живая копия

У кнопки там нет id , но это совершенно нормально, если она есть:

HTML:

 <div id='container'>
  <input type='button' id='theButton' value="Click Me, I'll Change">
  <br><input type='button' value="Click Me, I Won't Change">
</div>
  

JavaScript:

 $('#container').delegate('#theButton', 'click', function() {
  if (this.type === "button") {
    $(this).replaceWith(
      '<input id="theButton" type="image" src="'   imageSrc   '">'
    );
  }
  else {
    $(this).replaceWith(
      '<input id="theButton" type="button" value="Click Me, I'll Change">'
    );
  }
});
  

Живая копия


Не по теме: Поскольку вам все равно придется заменить элемент для поддержки IE, я бы рекомендовал иметь только одну копию кода и использовать ее во всех браузерах. Замена элемента обходится не так дорого, даже в браузерах, которые позволяют его изменять.

Комментарии:

1. Обратите внимание на то, что вы отклонились от темы, мне нужно изменить много кнопок, а скрипт, отличный от IE, работает быстрее.

2. Добавит ли делегат щелчок к элементу body? Я не совсем понимаю это!

3. @Mild Fuzz: Правильно. Это удобный синтаксис jQuery для общего метода, называемого делегированием событий . Если они не остановлены, большинство событий DOM перемещаются от элемента, на котором они фактически произошли, к родительскому элементу этого элемента, затем к родительскому элементу родительского элемента и т.д. Итак, если есть контейнер для всех этих кнопок, вы можете использовать его (вместо «body»). Нажатия будут начинаться с кнопок, но переходить в контейнер, где они будут обработаны. jQuery обработает проверку того, что событие началось с элемента, соответствующего указанному вами селектору, и вызовет вашу функцию, если это так.

4. @Mild Fuzz: Я обновил примеры в конце, надеюсь, они более понятны.

Ответ №2:

Вы не можете динамически изменять тип элемента ввода в Internet Explorer. Вы должны удалить старый ввод и добавить новый ввод

Комментарии:

1. это то, что делает скрипт только для IE