Yiiでcolorpicker widgetを作ってみました。

Yiiのwidgetを理解するために、datepicker widgetを参考にcolorpicker widgetを作成してみました。

まず最初に、colorpickerとして、jquery minicolorsを利用しますので、関係ファイルをダウンロードし、protected/extensions/colorPicker/assets/以下に設置します。

次に、protected/extensions/colorPicker/colorPicker.phpにwidgetの内容を記述します。widgetの構成は、おおまかには以下のような感じになります。

class ColorPicker extends CWidget
{
  //widgetに渡したい引数はpublicで宣言しておく
  public $model;

  //widgetの初期化
  public function init() 
  {
  }

  //このwidgetが表示するHTMLタグを書き出す
  public function run()
  {
  }
}

で、datepickerを参考に作成したcolorpickerは以下のような感じです。なお、widgetを作成するときはCWidgetを継承するのですが、今回はフォームの入力欄を利用するのでCInputWidgetを継承します。

class ColorPicker extends CInputWidget
{
  /**
   * @var array minicolorsに渡すオプション
   */
  public $defaultOptions;

  /**
   * @var string デフォルトで選択する色
   */
  private $_defaultColor="#eeeeee";
  /**
   * @var string asset url
   */
  protected $_assetsUrl;

    /**
     * widgetの初期化
     * minicolorsのjsとcssファイルをassetsに設置する。
     */
    public function init() 
    {
        if (Yii::getPathOfAlias('ext.colorPicker.assets') === false)
            Yii::setPathOfAlias('ext.colorPicker.assets', realpath(dirname(__FILE__) . '/..'));

        $cs=Yii::app()->getClientScript();
        $cs->registerScriptFile($this->getAssetsUrl() . "/jquery.minicolors.js"); 
        $cs->registerCssFile($this->getAssetsUrl() . "/jquery.minicolors.css");

        parent::init();
    }

    /**
     * Returns 公開assetsディレクトリのURLを返す
     * @return string the URL
     */
    public function getAssetsUrl() 
    {
        if (isset($this->_assetsUrl))
            return $this->_assetsUrl;
        else 
        {
            $assetsPath = Yii::getPathOfAlias('ext.colorPicker.assets');
            $assetsUrl = Yii::app()->assetManager->publish($assetsPath, false, -1, YII_DEBUG);
            return $this->_assetsUrl = $assetsUrl;
        }
    }

  /**
   * 表示するHTMLタグを書き出す
   * @see CWidget::run()
   */
  public function run()
  {
    list($name,$id)=$this->resolveNameID();

    if(isset($this->htmlOptions['id']))
      $id=$this->htmlOptions['id'];
    else
      $this->htmlOptions['id']=$id;
    if(isset($this->htmlOptions['name']))
      $name=$this->htmlOptions['name'];

    //colorpicker用のinputフィールドを書き出す
    if($this->hasModel())
    {
      echo CHtml::activeTextField($this->model,$this->attribute,$this->htmlOptions);
    }
    else
    {
      echo CHtml::textField($name,$this->value,$this->htmlOptions);
    }

    if(!empty($this->value))
      $this->defaultOptions['defaultValue']=$this->value;
    else if(empty($this->defaultOptions['defaultValue']))
      $this->defaultOptions['defaultValue']=$this->_defaultColor;

    //minicolorsに渡すオプションをJavascriptに変換
    $options=CJavaScript::encode($this->defaultOptions);
    //minicolorsをregisterScriptで登録
    $js = "jQuery('#{$id}').minicolors($options);";
    $cs=Yii::app()->getClientScript();
    $cs->registerScript(__CLASS__.'#'.$id,$js);
  }
}

なお、このwidgetを利用するには、ビューなどで以下のように書けばよいです。

<?php $this->widget('ext.colorPicker.colorPicker', array(
        'model'=>$model,
        'attribute'=>'bgcolor',
        'value'=>$model->bgcolor,
        'defaultOptions'=>array(
          'defaultValue'=>'#eeeeee',
          )));?>

また、

$('INPUT.minicolors').minicolors({
  defaultValue: '#eeeeee',
  animationSpeed: 100,
  change: function(hex, opacity) {
    console.log(hex + ' - ' + opacity);
  }
});

のようにminicolorsのオプションを設定するには、

<?php $this->widget('ext.colorPicker.colorPicker', array(
        'model'=>$model,
        'attribute'=>'bgcolor',
        'value'=>$model->bgcolor,
        'defaultOptions'=>array(
          'defaultValue'=>'#eeeeee',
          'animationSpeed'=>100,
          'change'=>'js:function(hex, opacity) {
                          console.log(hex + \' - \' + opacity);
                        }',
          )));?>

のようにします。
この際、minicolorsのオプションとして、Javascriptの処理を記述する場合は、先頭に「js:」をつけておく必要があります。

投稿日:
カテゴリー: php タグ: