1、TbActiveForm.php文件
分析:TbActiveForm的type属性的不同,通过getInputClassName()会引用不同的文件
Yii::import('bootstrap.widgets.input.TbInput');

/**
* Bootstrap active form widget.
*/

class TbActiveForm extends CActiveForm
{
// Form types.
const TYPE_VERTICAL = 'vertical';
const TYPE_INLINE = 'inline';
const TYPE_HORIZONTAL = 'horizontal';
const TYPE_SEARCH = 'search';

// Input classes.
const INPUT_HORIZONTAL = 'bootstrap.widgets.input.TbInputHorizontal';
const INPUT_INLINE = 'bootstrap.widgets.input.TbInputInline';
const INPUT_SEARCH = 'bootstrap.widgets.input.TbInputSearch';
const INPUT_VERTICAL = 'bootstrap.widgets.input.TbInputVertical';
 
由以上代码可知,需要更改的文件有TbInput TbInputHorizontal TbInputInline TbInputSearch TbInputVertical,对应于以下文件
 
2、TbInput 文件添加以下代码
分析:此类为抽象类,所以不能被实例化。调用抽象类必定是写子类实例出对象。在第三段代码中调用此抽象方法有很高的重用性,不用管Vertical、Horizontal这些参数设置由于为抽象方法(效果如同接口interface),子类TbInputVertical TbInputHorizontal TbInputInline TbInputSearch中则必须重写datetimepickerField()的具体方法。
TbInput 继承于 CInputWidget 继承于 Widget 含有getController()方法 继承于 CBaseController 继承于 CComponent base文件夹中
        //新添加datetimepicker
        const TYPE_DATETIMEPICKER = 'datetimepicker';
 
abstract protected function datetimepickerField();
 
case self::TYPE_DATETIMEPICKER:
    $this->datetimepickerField();
    break;
 
 
3、TbInputHorizontal TbInputVertical文件添加以下代码
分析:TbInputHorizontal TbInputVertical 继续于TbInput,datetimepickerField()重写抽象父类中的此抽象方法
TbInputInline继承于TbInputVertical  TbInputSearch继承于TbInputInline 因此都不需要添加
    protected function datetimepickerField()
    {
        if (isset($this->htmlOptions['options']))
        {
            $options = $this->htmlOptions['options'];
            unset($this->htmlOptions['options']);
        }

        echo $this->getLabel();
        echo '<div class="controls">';
        echo $this->getPrepend();
        $this->widget('bootstrap.widgets.TbDateTimePicker', array(
            'model' => $this->model,
            'attribute' => $this->attribute,
            'options' => isset($options) ? $options : array(),
            'htmlOptions' => $this->htmlOptions,
        ));
        echo $this->getAppend();
        echo $this->getError() . $this->getHint();
        echo '</div>';
    }
 
4、TbActiveForm.php文件添加以下代码
分析:当调用$form->datetimepickerRow($model, $attribute, $htmlOptions = array())时,会调用方法inputRow()和其参数TbInput::TYPE_DATETIMEPICKER,按理说TbInput是个抽象类,没法直接实例出对象。而在此处直接调用其静态常量,应该是在抽象类中的静态常量和方法,都能直接调用吧。(未实验)
    public function datetimepickerRow($model, $attribute, $htmlOptions = array())
    {
        return $this->inputRow(TbInput::TYPE_DATETIMEPICKER, $model, $attribute, null, $htmlOptions);
    }

注:此后是分析过程,不是需要添加的代码。

分析:inputRow() 方法源代码
    public function inputRow($type, $model, $attribute, $data = null, $htmlOptions = array())
    {
        ob_start();
        Yii::app()->controller->widget($this->getInputClassName(), array(
            'type' => $type,
            'form' => $this,
            'model' => $model,
            'attribute' => $attribute,
            'data' => $data,
            'htmlOptions' => $htmlOptions,
        ));
        return ob_get_clean();
    }
注:Yii::app()->controller的调用机制???
const INPUT_HORIZONTAL = 'bootstrap.widgets.input.TbInputHorizontal';
const INPUT_INLINE = 'bootstrap.widgets.input.TbInputInline';
const INPUT_SEARCH = 'bootstrap.widgets.input.TbInputSearch';
const INPUT_VERTICAL = 'bootstrap.widgets.input.TbInputVertical';
protected function getInputClassName()
{
if (isset($this->input))
    return $this->input;
else
{
switch ($this->type)
{
    case self::TYPE_HORIZONTAL:
        return self::INPUT_HORIZONTAL;
        break;
    case self::TYPE_INLINE:
        return self::INPUT_INLINE;
        break;
    case self::TYPE_SEARCH:
        return self::INPUT_SEARCH;
        break;
    case self::TYPE_VERTICAL:
    default:
        return self::INPUT_VERTICAL;
        break;
}
}
}
分析:调用了widget()方法,应该是抽象类CBaseController的widget()方法。
$this->getInputClassName()是根据type类型返回的相应的路径名并传入$className。
    public function widget($className,$properties=array(),$captureOutput=false)
    {
        if($captureOutput)
        {
            ob_start();
            ob_implicit_flush(false);
            $widget=$this->createWidget($className,$properties);
            $widget->run();
            return ob_get_clean();
        }
        else
        {
            $widget=$this->createWidget($className,$properties);
            $widget->run();
            return $widget;
        }
    }
分析:调用此类方法createWidget()。
注:$captureOutputtrue即返回html字符串,可以多次输出。
    public function createWidget($className,$properties=array())
    {
        $widget=Yii::app()->getWidgetFactory()->createWidget($this,$className,$properties);
                //exit(var_dump($widget));
        $widget->init();
                //exit(var_dump($widget));
        return $widget;
    }
 
分析:Yii::app()->getWidgetFactory()引用CWidgetFactory类
    public function createWidget($owner,$className,$properties=array())
    {
            //exit(var_dump($properties));
        $className=Yii::import($className,true);

        $widget=new $className($owner);
                //exit(var_dump(isset($this->widgets[$className])));
        if(isset($this->widgets[$className]))
            $properties=$properties===array() ? $this->widgets[$className] : CMap::mergeArray($this->widgets[$className],$properties);
        if($this->enableSkin)
        {
            if($this->skinnableWidgets===null || in_array($className,$this->skinnableWidgets))
            {
                $skinName=isset($properties['skin']) ? $properties['skin'] : 'default';
                if($skinName!==false && ($skin=$this->getSkin($className,$skinName))!==array())
                    $properties=$properties===array() ? $skin : CMap::mergeArray($skin,$properties);
            }
        }
        foreach($properties as $name=>$value)
            $widget->$name=$value;
                //exit(var_dump($widget->title));
        return $widget;
    }
分析:$className=Yii::import($className,true);通过import引入TbInputHorizontal TbInputInline TbInputSearch TbInputVertical中的任何一个子类。



posted on 2013-03-17 21:58  oo独舞  阅读(765)  评论(0编辑  收藏  举报