読者です 読者をやめる 読者になる 読者になる

Webエンジニア susumuis の技術ブログ

このブログの内容は個人の見解であり、所属する組織の公式見解ではありません

JavaScript+HTMLのみでテキストボックスのplaceholder実装メモ

Web

よくあるWebフォームの表現で、入力欄が空欄の時は「入力してください」のようなデフォルトの文言が出ていて、フォーカスを当てると空欄になるような仕掛けがあります。この表現は、placeholderとか、watermarks(透かし)と呼ばれるようで、HTML5の場合は標準機能のようです。また、jqueryを使用している場合はプラグインもあるようですが、既存のページで対応しなければいけない場合のための、ライブラリなしの実装しました。地味にはまったので、メモを残します。

なお以下の実装を導き出す際、@Otchyさんに助言を参考にさせていただきました。ありがとうございます。
http://twitter.com/otchy/status/37740505953468416
http://twitter.com/otchy/status/37742189345775616

実装手順

例えば備考フォームを作ろうとしたとします。

<html><body>
<form name="form1" method="GET" action="http://www.google.com">
	<textarea name="biko"></textarea>
	<input type="submit">
</form>
</body></html>

bikoの下にダミーのテキストエリアを配置し、displayをnoneにします。

<textarea name="biko_dummy" style="display: none">ご要望などはこちらに入力してください。</textarea>

これでは初期表示時に、ダミーが表示されません。元のHTMLをいじって、

<textarea name="biko" style="display: none"></textarea>
<textarea name="biko_dummy">ご要望などはこちらに入力してください。</textarea>

このようにすれば、問題ないですが、万が一、JavaScriptが動かなかった場合、メインが表示されなくなってしまいます。そこで、この書き方はせず、JavaScriptで以下のようにします。

document.forms.form1.biko.onblur();

ところが、この書き方ではIE8では、「戻る」ボタンがうまく動きませんでした。戻るボタンの時にJavaScriptが走ってしまい、その時点では、まだbikoの値がロードされていないようで、必ずダミーが出現してしまいます。

以下のようにすることで回避できました!
setTimeout(function() {document.forms.form1.biko.onblur()}, 10);

if (window.attachEvent) {
	window.attachEvent('onload', function() {document.forms.seisanForm.biko.onblur();});
} else {
	document.forms.seisanForm.biko.onblur();
}

完成コード

<html>
<body>
<form name="form1" method="GET" action="http://www.google.com">
	<textarea name="biko"></textarea>
	<textarea name="biko_dummy" style="display: none">ご要望などはこちらに入力してください。</textarea>
	<input type="submit">
</form>
<script type="text/javascript">
function onblurForm1Biko() {
	if (this.value == '') {
		this.style.display = 'none';
		this.form.biko_dummy.style.display = 'inline';
	}
}
function onfocusForm1BikoDummy() {
	this.form.biko.style.display = 'inline';
	this.style.display = 'none';
	this.form.biko.focus();
}

document.forms.form1.biko.onblur = onblurForm1Biko;
document.forms.form1.biko_dummy.onfocus = onfocusForm1BikoDummy;
if (window.attachEvent) {
	window.attachEvent('onload', function() {document.forms.seisanForm.biko.onblur();});
} else {
	document.forms.seisanForm.biko.onblur();
}
</script>

</body>
</html>

今回の場合、フォーム送信の時に "biko_dummy"の値も送信されてしまう問題があり、それを回避する場合は、textareaではなく、spanかなにかにすれば良いのですが、そうすると、デザイン調整とか、onfocusが使えないなど面倒なところもあるので、今回は上記実装で妥協しました。

以下、動作するサンプルです。

http://s-ishigami.appspot.com/files/placeholder.html

2011/02/18追記

setTimeoutよりもonloadの方が美しいと指摘を頂いたので、修正しました。ただ、既にonloadが使われている場合に厄介なので、attachEventを、(今回はIEだけの問題なので)存在チェック付きで使用しました。

やはり、jQuery使いたいですよね。