Каков наиболее точный способ эмулировать атрибут placeholder в браузерах, которые его не поддерживают изначально? - PullRequest
9 голосов
/ 07 апреля 2011

Недавно я рассматривал jquery / javascript-решения для эмуляции атрибута placeholder, но ни одно из них, похоже, не правильно. Общие проблемы:

  • Первоначальная поддержка браузера не используется
  • Форма может фактически содержать значение текста заполнителя
  • Невозможность распознать между заполнителем и вводом пользователем, если значения идентичны (Эй, мой адрес электронной почты IS user@example.com !! Почему он не отправляется? Эй, я хотел найти строку "Поиск "но это меня не отпустит!)
  • Сложно стилизовать или различить обычный текст и заполнитель текста
  • Навязчивая реализация (почти всегда. Я не хочу добавлять 2 деления на вход и таблицу стилей для этого)
  • Просто не работает. По крайней мере 2 из них на веб-сайте jQuery.

Я немного поиграл, пытаясь заставить это работать должным образом (используя несколько подсказок из части кода, который я уже видел), но это все еще требует работы. В частности, форма может содержать значение заполнителя. Приветствуются комментарии и моды к jsfiddle . (Примечание: демонстрация должна просматриваться в браузере без поддержки заполнителя) Большая часть кода, который я видел, принимает значение placeholder и вставляет его в сам ввод, что приводит к этой проблеме, я чувствую, что должен быть лучший способ.

Есть ли хорошее чистое решение, которое действительно работает ?

РЕДАКТИРОВАТЬ: я хочу подчеркнуть это: он должен вести себя так, как вы видите его в браузерах, которые поддерживают его как можно больше, и быть как можно более un , как показано в моем текущем коде , который не требует ничего, кроме включения скрипта и использования placeholder, как обычно для браузеров, которые его поддерживают.

ОБНОВЛЕНИЕ: Текущее решение @ DA - это пара исправлений ошибок, отличных от идеальных (см. Комментарии), хотелось бы, чтобы все это собралось на 100% и заставило стыдиться весь плохой и ошибочный код в сети.

ОБНОВЛЕНИЕ: Это работает с парой модов к коду DA, но это все еще не идеально, в основном в отношении динамически добавляемых полей ввода и существующих submit() привязок. Спасибо за помощь, я решил, что это того не стоит. Я знаю несколько человек, которые определенно будут использовать это все же. Это хороший трюк, но для меня не стоит даже 1% -ная вероятность того, что форма отправит что-то, что не предназначено, или неправильно прочитает ввод пользователя. Эта второстепенная функция просто не стоит головной боли, IE и pals могут справиться с ней, или она может быть реализована в каждом конкретном случае, если это действительно необходимо, например, если клиент требует этого. @DA еще раз спасибо, это лучшая реализация, которую я видел.

ЗАКЛЮЧЕНИЕ: Я думаю, что единственный способ преодолеть все эти проблемы - что-то вроде этого:

  • Скопировать значение заполнителя в новый элемент уровня блока
  • Добавить новый элемент к входу
  • Рассчитать высоту границы и отступа ввода и переместить новый элемент над ним как можно ближе к положению, в котором будет находиться текст
  • Используйте стандартные события размытия / изменения / фокуса, чтобы скрыть элемент, когда вход имеет значение или находится в фокусе

Таким образом, вам не нужно ничего делать при отправке или решать любые другие проблемы, которые могут возникнуть. Извините, демо-версии пока нет, я должен вернуться к работе, но я сохраню окончательную редакцию, когда все будет вместе.

Ответы [ 4 ]

4 голосов
/ 07 апреля 2011

"Большая часть кода, который я видел, берет значение заполнителя и вставляет его в сам ввод, что приводит к этой проблеме"

Ну, это в значительной степени то, что заменитель текста делает за кулисами (хотя это не буквально обновляет значение ввода).

Один из вариантов - что-то похожее на это:

http://fuelyourcoding.com/scripts/infield/

Идея в том, что вы перемещаете ЭТИКЕТКУ с помощью CSS, чтобы она находилась сверху поля и выглядела как текст-заполнитель. Обратите внимание, что LABEL не обязательно совпадает с текстом-заполнителем. LABEL важно иметь, особенно для обеспечения доступности, в то время как текст метки-заполнителя можно рассматривать как «текст справки» в дополнение к метке.

Другой вариант - это то, что вы делали: взять содержимое атрибута placeholder и переместить его в значение самого ввода через JS.

Когда вы зависаете, вы отправляете форму перед проверкой, чтобы увидеть, все ли еще существует поддельный текст заполнителя.

Чтобы обойти это, вы хотите прикрепить событие к отправке формы, которое перед отправкой формы сначала проверяет все поля ввода, захватывает их значения, сравнивает их с их атрибутами-заполнителями и, если оно совпадений, установите значение пустым.

UPDATE:

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

$('input[placeholder]').each(function(){

 if($(this).val() === $(this).attr('placeholder')){
      // in the odd situation where the field is prepopulated with
      // a value and the value just happens to match the placeholder,
      // then we need to flag it
      $(this).data('skipCompare','true');
  }    

// move the placeholder text into the field for the rest of the blank inputs
   if($(this).val().length===0){
       $(this).val($(this).attr('placeholder'))
   }

// move the placeholder text into the field for the rest of the blank inputs
  if($(this).val().length===0){
      $(this).val() = $(this).attr('placeholder');
  }


  $(this)
     .focus(function(){
           // remove placeholder text on focus
           if($(this).val()==$(this).attr('placeholder')){
               $(this).val('')
           }
     })
     .blur(function(){
         // flag fields that the user edits
         if( $(this).val().length>0 && $(this).val()==$(this).attr('placeholder')){
             $(this).data('skipCompare','true');
         }
         if ( $(this).val().length==0){
             // put the placeholder text back
             $(this).val($(this).attr('placeholder'));
         }
     })


 })

 $('#submitButton').click(function(){
   $('input[placeholder]').each(function(){
     if( !($(this).data('skipCompare')) && $(this).val() == $(this).attr('placeholder')     ){
         $(this).val('');
     };
     alert($(this).val());
   })
})

Уже поздно, и я устал, так что все это может быть совершенно неправильно. Никаких гарантий не дано. ;)

2 голосов
/ 07 апреля 2011

плагин jquery, который я написал недавно:

(function(){
    $.fn.inactiveText = function(inactiveClass, defaultValue){
        var a, b;
        this
            .data    ('defaultValue', defaultValue)
            .addClass('inactive')
            .focus(a=function(){
                var $this = $(this);
                if($this.hasClass(inactiveClass)){
                    (valFn.apply($this) == defaultValue) && $this.val('');
                    (valFn.apply($this) != defaultValue) && $this.removeClass(inactiveClass);
                }
    //            $this.hasClass(inactiveClass) && $this.valueIs(defaultValue).val('').end().valueIsNot(defaultValue).removeClass(inactiveClass);
            })
            .blur(b=function(){
                var $this = $(this);
                this.value || $this.addClass(inactiveClass).val(defaultValue);
            });
        this.each(a);
        this.each(b);

        this.setDefaultValue = function(d){
            this.each(a);
            defaultValue = d;
            this.each(b);
        };

        return this;
    };

    var valFn = $.fn.val;

    $.fn.val = function(v){
        if(typeof(v) == 'undefined'){
            var val = valFn.apply(this, arguments);
            return val == this.data('defaultValue') ? '' : val;
        }

        return valFn.apply(this, arguments);
    };
})();

Определите класс CSS для неактивного стиля (например, серый текст), и все готово.

обновленная скрипка: http://jsfiddle.net/cwolves/At8cu/1/

1 голос
/ 27 сентября 2014

Предположим, jQuery определен.

$(document).ready(function() {
    // Use native functionality if possible
    if (document.createElement('input').placeholder !== undefined) return;
    // Fallback code
    $('form').each(function(i, form) {
        var submitted = false;
        $(form).find('input[placeholder]').each(function(j, input) {
            addPlaceholder.call(input);
            $(input)
                .focus(removePlaceholder)
                .blur(addPlaceholder)
                ;
        });
        $(form).submit(function() {
            submitted = true;
            $(this).find('input[placeholder]').each(function(j, input) {
                removePlaceholder.call(input);
            });
        });
        function addPlaceholder() {
            if (!submitted && '' === $(this).val()) {
                $(this).val($(this).attr('placeholder')).addClass('placeholder');
            }
        }
        function removePlaceholder() {
            if ( $(this).hasClass('placeholder') &&
                 $(this).attr('placeholder') === $(this).val()
                 ) {
                $(this).val('').removeClass('placeholder');
            }
        }
    });
});

Стиль вашего заполнителя с CSS, чтобы он выглядел одинаково во всех браузерах:

            :-moz-placeholder { color: #bbb; opacity: 1; }
           ::-moz-placeholder { color: #bbb; opacity: 1; }
       :-ms-input-placeholder { color: #bbb; }
  ::-webkit-input-placeholder { color: #bbb; }
                 .placeholder { color: #bbb; }
...