Перейти к содержанию
  1. Блог/

Кроссбраузерный placeholder

·3 минуты
Назад в будущее Эта статья из старого блога и, возможно, устарела.

Добрый день.

Наконец-то дошли руки до написания первого тематического поста в блог. Им я начну цикл статей о jQuery плагинах, которые мы активно используем в студии. Итак, статья о такой полезной вещи как плэйсхолдер (placeholder).

Интро Placeholder это текст, по умолчанию стоящий в текстовых полях формы. Он подсказывает посетителю сайта, что же ему нужно написать в это поле. Сейчас всё чаще встречаются сайты, на которых он используется, поэтому тема, мне кажется, актуальна. Выглядит он вот так:

Example image

В некоторых ситуациях использование плэйсхолдера может избавить нас от необходимости ставить заголовок у поля формы, как например на картинке выше. В общем очень удобная и полезная штука.

В данный момент атрибут «placeholder» работает только в браузерах на движке Webkit (Google Chrome и Safari), то есть только очень маленький процент юзеров увидит его. А хочется порадовать всех.

Требования #

Плагин должен обрабатывать и текстовые поля (<input type=’text’>) и текстовые области (<textarea>) Для браузеров на движке Webkit оставлять их реализацию При отправке формы плэйсхолдеры должны убираться(несмотря на очевидность, в большинстве аналогичных плагинов это не сделано :) Плагин должен быть кроссбраузерным, т.е. под все браузеры, в которых вообще работает jQuery. Плагин должен быть удобным (подключил — юзай)

Реализация #

Основой всего в этом плагине для нас будет, так называемый, «Has Attribute» селектор ( мануал). Сначала была мысль выбрать все элементы, у которых есть атрибут «placeholder», и для каждого вешать нужные обработчики. Но в ходе тестирования стало понятно, что для текстовых полей будет одна обработка, а для текстовых областей другая, поэтому я решил сначала выбирать по селектору input[placeholder] и потом по textarea[placeholder].

Начнём с «каркаса». Сделан выход, если браузер на Webkit, создаётся нужный для работы класс (#a9a9a9 — цвет «родного» Webkit’овского плэйсхолдера)

$(function(){
	if ($.browser.safari) return; // Webkit has own placeholder, so we are free

	$('<style>').html('.jqueryPlaceholder{color:#a9a9a9!important;}').appendTo('head'); // Create placeholder class

	$('input[placeholder]').each(function(){ //Processing placeholders for input.texts
		// ...
	});

	$('textarea[placeholder]').each(function(){ //Processing placeholders for textareas
		// ...
	});

});

Затем ставим полям значения, которые у нас стоят в атрибуте «placeholder», и вешаем наш созданный класс. Тут я наткнулся на забавный баг, когда тестировал плагин в Firefox’е. Он заключался в том, что если написать что-нибудь в поле, то после обновления окна, плейсхолдер не появлялся (как и должно быть), а вот класс снова навешивался. После скрупулезного дебага выяснилось, что Огнелис при обновлении окна не очищает форму. Это, в принципе, удобно, но в данном случае было нам вредно. Для исправления проблемы я просто добавил ещё одно условие.

if(this.value == '' || this.value == $(this).attr('placeholder')){ // (Mozzi refresh fix)
	$(this).addClass('jqueryPlaceholder');
	this.value = $(this).attr('placeholder');
};

Дальше, всё просто и очевидно. Вешаем обработчики событий focus и blur на наши элементы.

$(this).focus(function(){
	if($(this).val() == $(this).attr('placeholder')){
		$(this)
			.removeClass('jqueryPlaceholder')
			.val('');
	}
});

$(this).blur(function(){
	if($(this).val() == ''){
		$(this)
			.addClass('jqueryPlaceholder')
			.val($(this).attr('placeholder'));
	}
});

Для текстовых областей всё аналогично, за исключением того, что вместо $(this).val() мы используем this.value, по причине что в первом случае в некоторых браузерах странно определяется содержимое. Ну и заодно немного разгружаем жквери. :)

Базовый функционал плагина сделан, всё работает, но не очищаются поля при сабмите. Сделаем и это. Для этого находим все формы на странице (так как их обычно немного, не будем устраивать гонки за скоростью), и вешаем на их сабмит обработчик. Он будет искать все текстовые поля и области и проверять, не стоит ли в них текст плэйсхолдера. Если стоит — очищаем.

$('form').each(function(){ // Processing "clear on submit"
	$(this).submit(function(){
		$(this).find("input").each(function(){
			if($(this).val() == $(this).attr('placeholder')) $(this).val('');
		});
		$(this).find("textarea").each(function(){
			if(this.value == $(this).attr('placeholder')) this.value = '';
		});
	});
});

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

Outro #

Надеюсь вам пригодится этот плагин. Любые багрепорты, пожелания или вопросы можете оставлять в комментариях, или присылать на [email protected].

Спасибо за внимание.