お手軽高機能!Closure UI【goog.ui.Button】

2012.10.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Closure Libraryに用意されている「goog.ui.Button」は、ネイティブボタンを表示するコンポーネントです。コンポーネント生成時にレンダラを指定することでネイティブボタン以外のアピアランスにすることも可能です。

デモ

Buttonコンポーネントを「描画(render)」と「装飾(decorate)」で表示したデモです。デフォルトレンダラによるButtonコンポーネントに加えて「FlatButtonRenderer」および「LinkButtonRenderer」によるButtonも同様に表示しています。

Renderer ID Demo enabled Note
Default
(NativeButtonRenderer)
button1
div要素にButtonコンポーネントをrenderしたもの。
button2 input(button)要素にButtonコンポーネントをdecorateしたもの。
FlatButtonRenderer flatbutton1
FlatButtonRendererをレンダラとしてdiv要素にrenderしたもの。
flatbutton2
Disabled Flat Button
FlatButtonRendererをレンダラとしてdiv要素にdecorateしたもの。
LinkButtonRenderer linkbutton1
LinkButtonRendererをレンダラとしてdiv要素にrenderしたもの。
linkbutton2 LinkButtonRendererをレンダラとしてdiv要素にdecorateしたもの。

デモコード

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>goog.ui.Button</title>
    <script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>
    <script>
      goog.require('goog.events');
      goog.require('goog.events.EventType');
      goog.require('goog.ui.decorate');
      goog.require('goog.ui.Button');
      goog.require('goog.ui.FlatButtonRenderer');
      goog.require('goog.ui.LinkButtonRenderer');
    </script>
    <link rel="stylesheet" href="http://closure-library.googlecode.com/svn/trunk/closure/goog/css/common.css">
    <link rel="stylesheet" href="http://closure-library.googlecode.com/svn/trunk/closure/goog/css/button.css">
    <link rel="stylesheet" href="http://closure-library.googlecode.com/svn/trunk/closure/goog/css/flatbutton.css">
    <link rel="stylesheet" href="http://closure-library.googlecode.com/svn/trunk/closure/goog/css/linkbutton.css">
  </head>
  <body>
    <table class="custom">
      <thead>
        <tr>
          <th width="200px">Renderer</th>
          <th width="80px">ID</th>
          <th width="200px">Demo</th>
          <th width="60px">enabled</th>
          <th>Note</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th rowspan="2">Default<br />(NativeButtonRenderer)</th>
          <th>button1</th>
          <td><div id="button1"></div></td>
          <td><input id="b1_checkbox" type="checkbox" checked/></td>
          <td>div要素にButtonコンポーネントをrenderしたもの。</td>
        </tr>
        <tr>
          <th>button2</th>
          <td><input id="button2" type="button" title="Tooltip extracted from title" value="Disabled Button" disabled /></td>
          <td><input id="b2_checkbox" type="checkbox"/></td>
          <td>input(button)要素にButtonコンポーネントをdecorateしたもの。</td>
        </tr>
        <tr>
          <th rowspan="2">FlatButtonRenderer</th>
          <th>flatbutton1</th>
          <td><div id="flatbutton1"></div></td>
          <td><input id="fb1_checkbox" type="checkbox" checked/></td>
          <td>FlatButtonRendererをレンダラとしてdiv要素にrenderしたもの。</td>
        </tr>
        <tr>
          <th>flatbutton2</th>
          <td><div id="flatbutton2" class="goog-flat-button goog-flat-button-disabled" title="Tooltip extracted from title">Disabled Flat Button</div></td>
          <td><input id="fb2_checkbox" type="checkbox"/></td>
          <td>FlatButtonRendererをレンダラとしてdiv要素にdecorateしたもの。</td>
        </tr>
        <tr>
          <th rowspan="2">LinkButtonRenderer</th>
          <th>linkbutton1</th>
          <td><div id="linkbutton1"></div></td>
          <td><input id="lb1_checkbox" type="checkbox" checked/></td>
          <td>LinkButtonRendererをレンダラとしてdiv要素にrenderしたもの。</td>
        </tr>
        <tr>
          <th>linkbutton2</th>
          <td><div id="linkbutton2" class="goog-link-button goog-link-button-disabled" title="Tooltip extracted from title">Disabled Link Button</div></td>
          <td><input id="lb2_checkbox" type="checkbox"/></td>
          <td>LinkButtonRendererをレンダラとしてdiv要素にdecorateしたもの。</td>
        </tr>
      </tbody>
    </table>
    <script>
      var button1 = new goog.ui.Button('Enabled Button');
      button1.render(goog.dom.getElement('button1'));
      button1.setTooltip('I changed the tooltip using setTooltip() after the button was rendered.');
      
      button1.addEventListener(goog.ui.Component.EventType.ACTION,
          function(event) {
            var newCaption = window.prompt('Enter new caption for button:');
            button1.setCaption(newCaption || 'Empty');
          });
      
      goog.events.listen(goog.dom.getElement('b1_checkbox'),
          goog.events.EventType.CLICK,
          function(event) {
            button1.setEnabled(event.target.checked);
            button1.setCaption(event.target.checked ? 'Enabled Button' : 'Disabled Button');
          });
      
      var button2 = new goog.ui.Button();
      button2.decorate(goog.dom.getElement('button2'));
      
      button2.addEventListener(goog.ui.Component.EventType.ACTION,
          function(event) {
            alert('The value of the button is: ' + button2.getValue());
          });
      
      goog.events.listen(goog.dom.getElement('b2_checkbox'),
          goog.events.EventType.CLICK,
          function(event) {
            button2.setEnabled(event.target.checked);
            button2.setValue(event.target.checked ? 'Enabled Button' : 'Disabled Button');
          });
      
      var flatbutton1 = new goog.ui.Button('Enabled Flat Button', goog.ui.FlatButtonRenderer.getInstance());
      flatbutton1.render(goog.dom.getElement('flatbutton1'));
      flatbutton1.setTooltip('I changed the tooltip using setTooltip() after the button was rendered.');
      
      flatbutton1.addEventListener(goog.ui.Component.EventType.ACTION,
          function(event) {
            var newCaption = window.prompt('Enter new caption for button:');
            flatbutton1.setCaption(newCaption || 'Empty');
          });
      
      goog.events.listen(goog.dom.getElement('fb1_checkbox'),
          goog.events.EventType.CLICK,
          function(event) {
            flatbutton1.setEnabled(event.target.checked);
            flatbutton1.setCaption(event.target.checked ? 'Enabled Flat Button' : 'Disabled Flat Button');
          });
      
      var flatbutton2 = goog.ui.decorate(goog.dom.getElement('flatbutton2'));
      
      flatbutton2.addEventListener(goog.ui.Component.EventType.ACTION,
          function(event) {
            alert('The caption of the button is: ' + flatbutton2.getCaption());
          });
      
      goog.events.listen(goog.dom.getElement('fb2_checkbox'),
          goog.events.EventType.CLICK,
          function(event) {
            flatbutton2.setEnabled(event.target.checked);
            flatbutton2.setCaption(event.target.checked ? 'Enabled Flat Button' : 'Disabled Flat Button');
          });
      
      var linkbutton1 = new goog.ui.Button('Enabled Link Button', goog.ui.LinkButtonRenderer.getInstance());
      linkbutton1.render(goog.dom.getElement('linkbutton1'));
      linkbutton1.setTooltip('I changed the tooltip using setTooltip() after the button was rendered.');
      
      linkbutton1.addEventListener(goog.ui.Component.EventType.ACTION,
          function(event) {
            var newCaption = window.prompt('Enter new caption for button:');
            linkbutton1.setCaption(newCaption || 'Empty');
          });
      
      goog.events.listen(goog.dom.getElement('lb1_checkbox'),
          goog.events.EventType.CLICK,
          function(event) {
            linkbutton1.setEnabled(event.target.checked);
            linkbutton1.setCaption(event.target.checked ? 'Enabled Link Button' : 'Disabled Link Button');
          });
      
      var linkbutton2 = goog.ui.decorate(goog.dom.getElement('linkbutton2'));
      
      linkbutton2.addEventListener(goog.ui.Component.EventType.ACTION,
          function(event) {
            alert('The caption of the button is: ' + linkbutton2.getCaption());
          });
      
      goog.events.listen(goog.dom.getElement('lb2_checkbox'),
          goog.events.EventType.CLICK,
          function(event) {
            linkbutton2.setEnabled(event.target.checked);
            linkbutton2.setCaption(event.target.checked ? 'Enabled Link Button' : 'Disabled Link Button');
          });
    </script>
  </body>
</html>

使い方

Buttonコンポーネントはインスタンスを生成し、指定した要素に「描画(render)」もしくは指定した要素を「装飾(decorate)」して利用します。

Closure Libraryのロード

<script src="http://closure-library.googlecode.com/svn/trunk/closure/goog/base.js"></script>
<script>
  goog.require('goog.events');
  goog.require('goog.events.EventType');
  goog.require('goog.ui.decorate');
  goog.require('goog.ui.Button');
  goog.require('goog.ui.FlatButtonRenderer');
  goog.require('goog.ui.LinkButtonRenderer');
</script>
6行目
Closure Libraryのbase.jsをロードします。
(このbase.jsをロードした場合には多くのスクリプト群がロードされる為、リリースするWebアプリケーションではこの形式は取りません。通常はClosure Libraryによる依存性管理およびClosure Compilerによるスクリプトの統合が用いられます。)
7~14行目
必要とするClosure Libraryを宣言します。

標準スタイルのロード

<link rel="stylesheet" href="http://closure-library.googlecode.com/svn/trunk/closure/goog/css/common.css">
<link rel="stylesheet" href="http://closure-library.googlecode.com/svn/trunk/closure/goog/css/button.css">
<link rel="stylesheet" href="http://closure-library.googlecode.com/svn/trunk/closure/goog/css/flatbutton.css">
<link rel="stylesheet" href="http://closure-library.googlecode.com/svn/trunk/closure/goog/css/linkbutton.css">
15~18行目
Buttonコンポーネントに標準で用意されているスタイル定義をロードします。UIコンポーネントには専用のスタイルが定義されたCSSファイルが用意されているものがあります。通常はクラス名と同様の名称(goog.ui.Button→button.css)になっているので直ぐに見つかると思います。

ID:button1についての処理

Buttonコンポーネントのインスタンスを生成して「ID:button1」のdiv要素へ描画(render)しています。

HTML

<td><div id="button1"></div></td>
<td><input id="b1_checkbox" type="checkbox" checked/></td>
35行目
Buttonコンポーネントを子要素として追加するdiv要素です。
36行目
Buttonコンポーネントの「enabled」を制御する為に用意したinput(checkbox)要素です。

JavaScript

var button1 = new goog.ui.Button('Enabled Button');
button1.render(goog.dom.getElement('button1'));
button1.setTooltip('I changed the tooltip using setTooltip() after the button was rendered.');

button1.addEventListener(goog.ui.Component.EventType.ACTION,
    function(event) {
      var newCaption = window.prompt('Enter new caption for button:');
      button1.setCaption(newCaption || 'Empty');
    });

goog.events.listen(goog.dom.getElement('b1_checkbox'),
    goog.events.EventType.CLICK,
    function(event) {
      button1.setEnabled(event.target.checked);
      button1.setCaption(event.target.checked ? 'Enabled Button' : 'Disabled Button');
    });
74行目
ボタンに表示する文字列をコンストラクタ引数としてButtonコンポーネントのインスタンスを生成しています。
75行目
生成したButtonコンポーネントをdiv要素(ID:button1)に描画しています。
76行目
マウスカーソルがロールオーバーされた際に表示されるツールチップを設定しています。
78~82行目
Buttonコンポーネントのリスナにイベントハンドラを追加します。
Buttonコンポーネントの押下はコンポーネント共有のイベント種別「goog.ui.Component.EventType.ACTION」をハンドリングし、イベントハンドラの追加には「goog.events.EventTarget」から継承している「addEventListener」メソッドを利用しています。(goog.events.listenによるイベントハンドリングも可能です。)
85~90行目
チェックボックスのクリックイベントをハンドリングします。Buttonコンポーネントの活性状態およびラベル(キャプション)を制御しています。

ID:button2についての処理

Buttonコンポーネントのインスタンスを生成して「ID:button2」のinput要素を装飾(decorate)しています。

HTML

<td><input id="button2" type="button" title="Tooltip extracted from title" value="Disabled Button" disabled /></td>
<td><input id="b2_checkbox" type="checkbox"/></td>
41行目
Buttonコンポーネントとして装飾するinput要素です。初期値では非活性としています。
42行目
Buttonコンポーネントの「enabled」を制御する為に用意したinput(checkbox)要素です。

JavaScript

var button2 = new goog.ui.Button();
button2.decorate(goog.dom.getElement('button2'));

button2.addEventListener(goog.ui.Component.EventType.ACTION,
    function(event) {
      alert('The value of the button is: ' + button2.getValue());
    });

goog.events.listen(goog.dom.getElement('b2_checkbox'),
    goog.events.EventType.CLICK,
    function(event) {
      button2.setEnabled(event.target.checked);
      button2.setValue(event.target.checked ? 'Enabled Button' : 'Disabled Button');
    });
91~92行目
Buttonコンポーネントのインスタンスを生成し、input要素をButtonコンポーネントとして装飾(decorate)しています。
94~97行目
Buttonコンポーネントのリスナにイベントハンドラを追加しています。
Buttonコンポーネントの押下はコンポーネント共有のイベント種別「goog.ui.Component.EventType.ACTION」をハンドリングし、イベントハンドラの追加には「goog.events.EventTarget」から継承している「addEventListener」メソッドを利用します。
99~104行目
チェックボックスのクリックイベントをハンドリングします。Buttonコンポーネントの活性状態およびラベル(キャプション)を制御しています。

ID:flatbutton1についての処理

FlatButtonRendererをレンダラとしてButtonコンポーネントのインスタンスを生成し、「ID:flatbutton1」のdiv要素へ描画(render)しています。

HTML

<td><div id="flatbutton1"></div></td>
<td><input id="fb1_checkbox" type="checkbox" checked/></td>
48行目
Buttonコンポーネントを子要素として追加するdiv要素です。
49行目
Buttonコンポーネントの「enabled」を制御する為に用意したinput(checkbox)要素です。

JavaScript

var flatbutton1 = new goog.ui.Button('Enabled Flat Button', goog.ui.FlatButtonRenderer.getInstance());
flatbutton1.render(goog.dom.getElement('flatbutton1'));
flatbutton1.setTooltip('I changed the tooltip using setTooltip() after the button was rendered.');

flatbutton1.addEventListener(goog.ui.Component.EventType.ACTION,
    function(event) {
      var newCaption = window.prompt('Enter new caption for button:');
      flatbutton1.setCaption(newCaption || 'Empty');
    });

goog.events.listen(goog.dom.getElement('fb1_checkbox'),
    goog.events.EventType.CLICK,
    function(event) {
      flatbutton1.setEnabled(event.target.checked);
      flatbutton1.setCaption(event.target.checked ? 'Enabled Flat Button' : 'Disabled Flat Button');
    });
106行目
ボタンに表示する文字列およびレンダラをコンストラクタ引数としてButtonコンポーネントのインスタンスを生成しています。
レンダラはメモリ節約の為シングルトンで提供されているので「getInstance」メソッドでインスタンスを取得します。
107行目
生成したButtonコンポーネントをdiv要素(ID:flatbutton1)に描画しています。
108行目
マウスカーソルがロールオーバーされた際に表示されるツールチップを設定しています。
110~114行目
Buttonコンポーネントのリスナにイベントハンドラを追加しています。
Buttonコンポーネントの押下はコンポーネント共有のイベント種別「goog.ui.Component.EventType.ACTION」をハンドリングし、イベントハンドラの追加には「goog.events.EventTarget」から継承している「addEventListener」メソッドを利用します。(goog.events.listenによるイベントハンドリングも可能です。)
116~121行目
チェックボックスのクリックイベントをハンドリングします。Buttonコンポーネントの活性状態およびラベル(キャプション)を制御しています。

ID:flatbutton2についての処理

「goog.ui.decorate」メソッドを利用して既存要素「ID:flatbutton2」の装飾を行なっています。

HTML

<td><div id="flatbutton2" class="goog-flat-button goog-flat-button-disabled" title="Tooltip extracted from title">Disabled Flat Button</div></td>
<td><input id="fb2_checkbox" type="checkbox"/></td>
54行目
Buttonコンポーネントとして装飾するdiv要素です。どのように装飾するかを指定する為class属性に「goog-flat-button」および「goog-flat-button-disabled」を設定しています。「goog-flat-button-disabled」が指定されているので初期状態では非活性となります。
55行目
Buttonコンポーネントの「enabled」を制御する為に用意したinput(checkbox)要素です。

JavaScript

var flatbutton2 = goog.ui.decorate(goog.dom.getElement('flatbutton2'));

flatbutton2.addEventListener(goog.ui.Component.EventType.ACTION,
    function(event) {
      alert('The caption of the button is: ' + flatbutton2.getCaption());
    });

goog.events.listen(goog.dom.getElement('fb2_checkbox'),
    goog.events.EventType.CLICK,
    function(event) {
      flatbutton2.setEnabled(event.target.checked);
      flatbutton2.setCaption(event.target.checked ? 'Enabled Flat Button' : 'Disabled Flat Button');
    });
123行目
「goog.ui.decorate」メソッドを利用して、対象要素のclass属性を判別して自動的に装飾すると同時にButtonコンポーネントのインスタンスを取得しています。
125~128行目
Buttonコンポーネントのリスナにイベントハンドラを追加しています。
Buttonコンポーネントの押下はコンポーネント共有のイベント種別「goog.ui.Component.EventType.ACTION」をハンドリングし、イベントハンドラの追加には「goog.events.EventTarget」から継承している「addEventListener」メソッドを利用します。
130~135行目
チェックボックスのクリックイベントをハンドリングします。Buttonコンポーネントの活性状態およびラベル(キャプション)を制御しています。

ID:linkbutton1についての処理

LinkButtonRendererをレンダラとしてButtonコンポーネントのインスタンスを生成し、「ID:linkbutton1」のdiv要素へ描画(render)しています。

HTML

<td><div id="linkbutton1"></div></td>
<td><input id="lb1_checkbox" type="checkbox" checked/></td>
61行目
Buttonコンポーネントを子要素として追加するdiv要素です。
62行目
Buttonコンポーネントの「enabled」を制御する為に用意したinput(checkbox)要素です。

JavaScript

var linkbutton1 = new goog.ui.Button('Enabled Link Button', goog.ui.LinkButtonRenderer.getInstance());
linkbutton1.render(goog.dom.getElement('linkbutton1'));
linkbutton1.setTooltip('I changed the tooltip using setTooltip() after the button was rendered.');

linkbutton1.addEventListener(goog.ui.Component.EventType.ACTION,
    function(event) {
      var newCaption = window.prompt('Enter new caption for button:');
      linkbutton1.setCaption(newCaption || 'Empty');
    });

goog.events.listen(goog.dom.getElement('lb1_checkbox'),
    goog.events.EventType.CLICK,
    function(event) {
      linkbutton1.setEnabled(event.target.checked);
      linkbutton1.setCaption(event.target.checked ? 'Enabled Link Button' : 'Disabled Link Button');
    });
137行目
ボタンに表示する文字列およびレンダラをコンストラクタ引数としてButtonコンポーネントのインスタンスを生成しています。
レンダラはメモリ節約の為シングルトンで提供されているので「getInstance」メソッドでインスタンスを取得します。
138行目
生成したButtonコンポーネントをdiv要素(ID:flatbutton1)に描画しています。
139行目
マウスカーソルがロールオーバーされた際に表示されるツールチップを設定しています。
141~145行目
Buttonコンポーネントのリスナにイベントハンドラを追加しています。
Buttonコンポーネントの押下はコンポーネント共有のイベント種別「goog.ui.Component.EventType.ACTION」をハンドリングし、イベントハンドラの追加には「goog.events.EventTarget」から継承している「addEventListener」メソッドを利用します。(goog.events.listenによるイベントハンドリングも可能です。)
147~152行目
チェックボックスのクリックイベントをハンドリングします。Buttonコンポーネントの活性状態およびラベル(キャプション)を制御しています。

ID:linkbutton2についての処理

HTML

「goog.ui.decorate」メソッドを利用して既存要素「ID:linkbutton2」の装飾を行なっています。

<td><div id="linkbutton2" class="goog-link-button goog-link-button-disabled" title="Tooltip extracted from title">Disabled Link Button</div></td>
<td><input id="lb2_checkbox" type="checkbox"/></td>
67行目
Buttonコンポーネントとして装飾するdiv要素です。どのように装飾するかを指定する為class属性に「goog-link-button」および「goog-link-button-disabled」を設定しています。「goog-link-button-disabled」が指定されているので初期状態では非活性となります。
68行目
Buttonコンポーネントの「enabled」を制御する為に用意したinput(checkbox)要素です。

JavaScript

var linkbutton2 = goog.ui.decorate(goog.dom.getElement('linkbutton2'));

linkbutton2.addEventListener(goog.ui.Component.EventType.ACTION,
    function(event) {
      alert('The caption of the button is: ' + linkbutton2.getCaption());
    });

goog.events.listen(goog.dom.getElement('lb2_checkbox'),
    goog.events.EventType.CLICK,
    function(event) {
      linkbutton2.setEnabled(event.target.checked);
      linkbutton2.setCaption(event.target.checked ? 'Enabled Link Button' : 'Disabled Link Button');
    });
154行目
「goog.ui.decorate」メソッドを利用して、対象要素のclass属性を判別して自動的に装飾すると同時にButtonコンポーネントのインスタンスを取得しています。
156~159行目
Buttonコンポーネントのリスナにイベントハンドラを追加しています。
Buttonコンポーネントの押下はコンポーネント共有のイベント種別「goog.ui.Component.EventType.ACTION」をハンドリングし、イベントハンドラの追加には「goog.events.EventTarget」から継承している「addEventListener」メソッドを利用します。
161~166行目
チェックボックスのクリックイベントをハンドリングします。Buttonコンポーネントの活性状態およびラベル(キャプション)を制御しています。

まとめ

通常、renderではコンポーネントを挿入する位置を示す要素しかHTMLには表記されませんが、decorateを用いればコントロールのレイアウトを確認しながらもClosure Libraryが提供するコンポーネントの恩恵を受けることができるので、上手く使い分けると良いかと思います。
goog.ui.ButtonRendererを拡張して独自のアピアランスを持ったボタンを作成しても面白いかもしれませんね。

参照