テキストノードの作成

2015/05/23

前回に引き続き、Cape.JS の基本的な機能を紹介していきます。

今回のテーマはテキスト。指定された文字列をエスケープして埋め込む場合とエスケープしないで埋め込む場合に分けて説明します。


本題に入る前に、Cape.JS のコンポーネントクラスを定義する JavaScript プログラムを HTML ファイルから分離しておきましょう。プログラムが長くなってきたら、こうした方が扱いやすくなります。

前回の末尾で作った hello_message3.html<script> 要素の中身から HelloMessage クラスを定義している部分を抜き出して、新たに hello_message4.js という名前のファイルを作ります。

var HelloMessage = Cape.createComponentClass({
  render: function(m) {
    m.div({ class: 'container' }, function(m) {
      m.h1('Greetings from Cape.JS');
      m.div({ class: 'panel panel-default' }, function(m) {
        m.div('Hello, ' + this.root.data.name + '!',
          { class: 'panel-body' });
      });
    });
  }
});

そして、hello_message3.htmlhello_message4.html にリネームして、<body> 要素の中身を次のように変更してください。

  <div id="main" data-name="world"></div>
  <script src="./hello_message4.js"></script>
  <script>
    var component = new HelloMessage();
    component.mount('main');
  </script>

念のため、ブラウザで hello_message4.html を開いてみて、前回同様の画面表示になることを確認してください。


今回の目標は、「Hello, world!」の「world!」の部分を <strong></strong> で囲んで太字にすることです。hello_message4.js を次のように書き換えてください。

var HelloMessage = Cape.createComponentClass({
  render: function(m) {
    m.div({ class: 'container' }, function(m) {
      m.h1('Greetings from Cape.JS');
      m.div({ class: 'panel panel-default' }, function(m) {
        m.div({ class: 'panel-body' }, function(m) {
          m.text('Hello, ');
          m.strong(this.root.data.name + '!');
        });
      });
    });
  }
});

ブラウザで hello_message4.html を開くと、次のような画面表示になります:

画面表示

初登場のメソッドは text()strong() です。後者は <strong> 要素を仮想 DOM ツリーに追加するメソッドで div()p() の仲間です。text() メソッドは、テキストノード(要素の中身のうち、タグで囲まれていない部分)を仮想 DOM ツリーに追加します。

テキストノードを追加するメソッドとしては、もうひとつ sp() があります。これは半角スペース1個を仮想 DOM ツリーに追加するメソッドです。これを使えば、hello_message4.js は次のように書き換えられます:

var HelloMessage = Cape.createComponentClass({
  render: function(m) {
    m.div({ class: 'container' }, function(m) {
      m.h1('Greetings from Cape.JS');
      m.div({ class: 'panel panel-default' }, function(m) {
        m.div({ class: 'panel-body' }, function(m) {
          m.text('Hello,').sp();
          m.strong(this.root.data.name + '!');
        });
      });
    });
  }
});

このメソッドは、半角スペースの存在を強調したり、要素と要素の間に半角スペースを挿入したりする目的で使われます。


ところで、この text() メソッドで埋め込まれる文字列は、エスケープされます。すなわち、<& のような特殊文字列は &lt;&amp; のように自動的に変換されます。セキュリティの観点からはこの仕様が望ましいのですが、エスケープしたくない場合もあります。例えば、&x263a; のような実体参照を用いて文字列を埋め込みたい場合などです。

hello_message4.htmlhello_message5.html に、hello_message4.jshello_message5.js にコピーしてから、エディタで hello_message5.html を開いて <body> 要素の中身を次のように書き換えてください。

  <div id="main" data-name="&amp;#x263a;"></div>
  <script src="./hello_message5.js"></script>
  <script>
    var component = new HelloMessage();
    component.mount('main');
  </script>

ブラウザで hello_message5.html を開くと、次のような画面表示になります:

画面表示

文字列がエスケープされないようにするには、hello_message5.js を次のように書き換えます:

var HelloMessage = Cape.createComponentClass({
  render: function(m) {
    m.div({ class: 'container' }, function(m) {
      m.h1('Greetings from Cape.JS');
      m.div({ class: 'panel panel-default' }, function(m) {
        m.div({ class: 'panel-body' }, function(m) {
          m.text('Hello,').sp();
          m.strong({ innerHTML: this.root.data.name + '!' });
        });
      });
    });
  }
});

ブラウザをリロードすると、次のような画面表示になります:

画面表示

見えにくいかもしれませんが、画面に「スマイリーマーク」が表示されています。このように innerHTML オプションを用いると、要素の中身を「生の HTML」で指定できます。


次回は、Cape.JS を Ruby on Rails に組み込む方法について解説する予定です。