LoginSignup
19
14

More than 5 years have passed since last update.

contenteditable要素に対してplaceholder設定を実現する

Last updated at Posted at 2013-07-27

GoogleChrome30.0.1573.2 dev(Mac版)でのみ動作確認しています。

HTML5の機能として提供されるplaceholder属性ですが、とてもとても残念な事にinputタグのみでcontenteditable=trueの要素に対してはその効果を適用出来ません。

そんな中で、inputタグでplaceholderを利用して初期値を表示している箇所と、<div contenteditable=true>を利用して入力可能にしている場所があると、当然ユーザーから

『あれ、ここ(inputタグ)で表示してるこの初期表示をあそこ(contenteditable=true)にも表示できるようにしてよ』

とか言われる訳です。というか言われますよね?。私は言われました。
そこで懇切丁寧に説明して理解してくれるユーザーさんならいいんですが、
往々にして『仕様です!実装してください』とか言われる訳です。

完成予想図

以下の様に設定出来るようにjQueryプラグインとして実装を行います。

<head>
    <style type="text/css" media="screen">
      [data-placeholder][data-placeholderactive=true]::before {
        content: attr(data-placeholder);
        opacity: 0.5;
      }
    </style>
    <script src="jquery.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript" charset="utf-8">
      $(function() {
        $.setPlaceholder();
      });
    </script>
</head>
<body>
    <!-- placeholder有効時 -->
    <div contenteditable="true" data-placeholder="初期値" data-placeholderactive="true">
    </div>
    <!-- placeholder無効時 -->
    <div contenteditable="true" data-placeholder="初期値" data-placeholderactive="false">
    </div>
    <!-- あるいは -->
    <div contenteditable="true" data-placeholder="初期値">
    </div>
</body>

レシピ

HTML5(jQueryではありません)のdata属性と、CSSのcontentを利用します。

data属性

HTML5のdata属性に関しては、ここで説明するよりもHTML5.jpの独自データ属性辺りを見る方が100倍詳しく分かります。超簡単に言うと、data-*という属性を利用して独自データを定義出来るようになります。

contentプロパティ

CSSのcontentMDNのCSSリファレンス辺りが参考になるかと思います。こちらも超簡単に言うと、指定したセレクタに対して任意の文字や画像の挿入を行う事が出来るようになります。

contentプロパティには様々な設定を行う事が出来ますが、その中でattrという物が存在します。
MDNのリファレンスから引用すると…

要素の属性の値 X を文字列として返します。属性 X が存在しない場合は、空文字が返されます。

と書かれています。つまりattrはHTMLの属性を指定する事が出来るという訳です。
なんと、この属性はdata属性の場合でも設定する事が可能です。

今回はこれを利用してplaceholder機能を実現します。

調理開始

CSSの設定

CSSでは属性としてdata-placeholder及びdata-placeholderactiveが指定されていた要素が存在する場合に:beforecontent属性としてその要素の持つdata-placeholderを差し込む設定を行っています。
ここでは先ほどの完成予想図の通りのsytle設定をします。

[data-placeholder][data-placeholderactive=true]::before {
    content: attr(data-placeholder);
    opacity: 0.5;
}

HTMLの設定

完成予想図で書いた通りです。そのまま設定をします。
ここではdivタグで設定していますが、どんなタグでも問題ありません。
但しcontenteditable=trueに限定していないのでその点だけ注意が必要です。

<div contenteditable="true" data-placeholder="初期値" data-placeholderactive="true">

Javascriptの設定

CSSの設定とJavascriptの設定をしておけば、初期値としてplaceholderの表示までは行えます。但しこの設定だと当然フォーカスがあってもplaceholderは自動では消えません。そこでjavascriptでユーザーにより入力されたタイミングでplaceholderを削除するように実装を行います。

/**
 * ContetEditable領域に対するplaceholderを実現するための簡易なjQueryプラグインを提供します
 */
(function(jQuery) {
  /**
   * Placeholderが`無効`になった場合のイベントハンドラ
   */
  var inActiveHandler = function() {
    delete(this.dataset.placeholderactive);
  };

  /**
   * Placeholderが`有効`になった場合のイベントハンドラ
   */
  var activeHandler = function() {
    if (this.innerText.length !== 0) return;
    this.dataset.placeholderactive = 'true';
  };

  //=======================================================
  // 公開メソッド
  //=======================================================

  /**
   * 属性として`data-placeholder`を保持する要素に対して一括でplaceholder設定を行います。
   */
  jQuery.setPlaceholder = function() {
    $('[data-placeholder]').placeholder();
  };

  /**
   * 指定した要素にplacehodler要素をCSSのcontent属性を利用して設定します
   */
  jQuery.fn.placeholder = function() {
    this.on('change keydown keypress input', inActiveHandler)
        .on('blur', activeHandler);

    // 初期化時に再評価
    activeHandler.bind(this.get()[0])();

    return this;
  };
})(jQuery);

あとは、適当なタイミングで$.setPlaceholder()を呼び出します。
今回のサンプルだと、入力領域でキーボードを操作したタイミングでplaceholderが非表示になり、入力領域からフォーカスが外れたタイミングで何も入力されていなければplaceholderが復元します。

TODO

ちゃんとjQueryプラグイン化する。

作った => https://github.com/hikaruworld/jquery.contenteditable.placeholder

参考サイト

19
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
14