Closure LibraryのToolbarにinput type="text"を表示したい

Google Chrome Extension "History Plus"の開発Memo. version 2.0.0から大幅にLayoutを変更。Closure Libraryのtoolbarを使ってheader部分に制御する機能をまとめてみた。

この時ハマったのがtoolbarにinput tagを挿入できない。いや、表示するだけなら問題ないけど、選択したときにtoolbarがfocusを奪うので入力できない状態。

実現したいのはこんな感じ↓

image


< 2012/01/19 Modified >

Source Codeを追いかけてみた。

toolbarをrenderするときに
全ての子要素の"enterDocument" Methodが呼ばれて
"initializeDom"の中で
styleに"-webkit-user-select"が設定
されるから入力できなくなるみたい。

しょうがないので、描画し終わったあとにstyle属性を変更することで対応した。

goog.array.forEach(
  goog.dom.query('#header input'),
  function(element) {
    goog.style.setStyle(element, '-webkit-user-select', 'auto');
  });

詳細はGitHubで公開してるheaderview.jsを参照。

以下の記述は役に立たないので無視でお願いします。


思いついたのはgoog.ui.ComboBoxを利用する方法。menuを追加せずにcssを調整すれば上のような感じで実現できる。

でも、これをToolbar Objectで管理するためにaddChildしようとしても出来ない。addChildの引数はgoog.ui.Controlを継承してないといけない。

試行錯誤の結果。goog.ui.ComboBoxとgoog.ui.Controlの両方を継承したClassを定義し直して利用することにした。

goog.base.jsで提供されているgoog.inheritsはprototypeを上書きしてしまうので、ここを参考に次のような関数を定義。

/**
* Copy the properties. This method is called by historyplus.inherits.
*
* @param {Object} child Child property.
* @param {Object} parent Parent property.
*/
historyplus.copyProperties = function(child, parent) {
  for (var prop in parent) {
    if (typeof(child[prop]) == 'undefined') {
      child[prop] = parent[prop];
    }
  }
};


/**
* Inherit the properties and prototype methods from one constructor into another.
*
* @param {Function} child Child class.
* @param {Function} parent Parent class.
*/
historyplus.inherits = function(child, parent) {
  historyplus.copyProperties(child, parent);
  historyplus.copyProperties(child.prototype, parent.prototype);
};

これを使ってgoog.ui.ComboBoxとgoog.ui.Controlの両方を継承したClassを定義

goog.provide('historyplus.ComboBoxControl');

goog.require('goog.ui.Control');
goog.require('goog.ui.ComboBox');

historyplus.ComboBoxControl = function(content, opt_renderer, opt_domHelper) {
  // Inherits functions and properties from goog.ui.Control.
  historyplus.inherits(historyplus.ComboBoxControl, goog.ui.Control);

  goog.ui.Control.call(this, content, opt_renderer, opt_domHelper);

  goog.ui.ComboBox.call(this, opt_domHelper);
  this.renderer_ = opt_renderer ||
      goog.ui.registry.getDefaultRenderer(this.constructor);
  this.setContentInternal(content);
};
goog.inherits(historyplus.ComboBoxControl, goog.ui.ComboBox);

Source CodeはGitHubで公開しているので、そちらも参考に。もっとSmartな方法があるかもしれないけど、一応toolbar objectで管理できるのでスッキリ。

 

< Related Posts >