IE9 向けに placeholder を提供するライブラリをいくつか試してみたものの、どうもしっくり来るものがなく、自前で実装したのでメモ。
ただし、やっつけ実装なので、あくまでも実現方法の参考として見て頂きたい。
試したライブラリ
既存ライブラリのイマイチポイント 1
- ページをリロードすると placeholder が表示されなくなる
- placeholder と同じテキストを入力できない (勝手に placeholder と判断されて削除される)
- 何も入力していない状態で submit すると placeholder の内容が submit される
実装コード
$(function() {
var isPlaceholderSupported = (function() {
return 'placeholder' in document.createElement('input');
}());
if (isPlaceholderSupported) {
return;
}
$('[placeholder]')
.wrap('<div style="display:inline-block;position:relative"></div>')
.parent()
.on('mouseover', function() {
var parent = $(this);
var elm = parent.find('span');
var input = parent.find('[placeholder]');
elm.css('cursor', input.css('cursor'));
})
.end()
.each(function() {
var elm = $(this);
var text = elm.attr('placeholder');
var val = elm.val();
var paddingTop = Number(elm.css('padding-top').replace('px', ''));
var paddingLeft = Number(elm.css('padding-left').replace('px', ''));
var borderTop = Number(elm.css('border-top-width').replace('px', ''));
var borderLeft = Number(elm.css('border-left-width').replace('px', ''));
$('<span style="color:#999;display:inline-block;position:absolute"></span>')
.text(text)
.css({
top: paddingTop + borderTop,
left: paddingLeft + borderLeft,
visibility: (val === '' ? 'visible' : 'hidden')
})
.insertBefore(elm);
})
.on('focus', function() {
$(this).prev().css('visibility', 'hidden');
})
.on('blur', function() {
var elm = $(this);
if (elm.val() === '') {
elm.prev().css('visibility', 'visible');
}
})
.prev()
.on('mousedown', function() {
var elm = $(this);
var input = elm.next();
if (input.prop('disabled') || input.prop('readonly')) {
return;
}
elm.css('visibility', 'hidden');
input.focus();
return false;
})
;
});
コード適用時のHTMLイメージ:
適用前
<input type="text" placeholder="値を入力してください" />
適用後
<div style="display:inline-block; position:relative">
<span style="left:2px; top:3px; color:#999; display:inline-block; position:absolute; cursor:auto">値を入力してください</span>
<input type="text" />
</div>
工夫ポイント
- placeholder をサポートしているブラウザではそちらを使用するようにしている。
- value を使う代わりに span を input 上に重ねて表示する方式のため、リロードや submit しても input の内容に影響を与えない。
- placeholder が input の内容と同じ位置に表示されるよう、input の padding、border を考慮している。
- input と同じカーソルを placeholder に設定するようにしている。2
- placeholder にフォーカスが当たらないよう、placeholder の onmousedown で input にフォーカスを設定している。
やっつけポイント
- jQuery に依存している。3
- スタイルが style 属性にハードコーディングされている。4
- input を勝手に div で囲むため、場合によってはスタイルが崩れる。5
- input と placeholder のスタイル (フォントサイズ等) が微妙に違う6
- 毎回、input や placeholder の Element を取得している。(
prev()
とか) 7 - コードのコピペが多い (
prev()
とか placeholder の表示切替部分とか) 8 - input ごとにイベントを登録している。 9
結論
IE9 をサポートしなくて良いように根回ししましょう。