Common properties for JUI widgets

I’m happy to present a possible solution to the CWidgetFactory common jui properties problem.

1. Add this extended CWidgetFactory class




<?php

/**

 * Creates a new widget based on the given class name and initial properties.

 * Priority order:

 * 1. Actual parameter: $properties

 * 2. Specific widget class factory config

 * 3. CJui common factory config

 * 4. If skin is defined (as above), use skin properties from 

 *    widget specific skin file in active Yii theme

 * @param CBaseController $owner the owner of the new widget

 * @param string $className the class name of the widget. This can also be a path alias (e.g. system.web.widgets.COutputCache)

 * @param array $properties the initial property values (name=>value) of the widget.

 * @return CWidget the newly created widget whose properties have been initialized with the given values.

 */

class EWidgetFactory extends CWidgetFactory

{

  public function createWidget($owner,$className,$properties=array())

  {

    $commonProperties='CJuiWidget';

    $applyTo='CJui';


    $widgetName=Yii::import($className);

    if (isset($this->widgets[$commonProperties]) && strpos($widgetName,$applyTo)===0)

    {

      // Merge widget class specific factory config and the $properties parameter

      // into $properties.

      if(isset($this->widgets[$widgetName]))

        $properties=$properties===array() ? $this->widgets[$widgetName] : CMap::mergeArray($this->widgets[$widgetName],$properties);


      // Merge CJui common factory config and the $properties parameter

      // into the $properties parameter of parent call.

      return parent::createWidget($owner,$className,CMap::mergeArray($this->widgets[$commonProperties],$properties));

    }


    return parent::createWidget($owner,$className,$properties);

  }

}



This class can be further improved e.g. currently only CJui… is supported and there’s no support for excluding some jui widgets.

2. Add fake widget class name to widgetFactory component config




'widgetFactory'=>array(

  'class'=>'EWidgetFactory',

  ...

  'widgets' => array(

    'CJuiWidget' => array(

      'themeUrl'=>'/js/jquery-ui-1.8/themes', // example

      'theme'=>'ui-lightness', // example

      ...

    ),

  ),

),



Edit: Fixed the bug that common properties had precedence over widget class properties. Inserted one statement from the parent class.

Edit2: Changed EJuiCommonProperties to CJuiWidget

/Tommy

Can I have your thoughts about this, please. Useful or not? Suggestions for better “fake class name” than ‘EJuiCommonProperties’? I think applyTo may need to be array(‘CJui’, ‘EJui’, ‘…’) etc.

/Tommy

I hardly ever use any CJuiWidgets but your approach looks good. I just would not use that fake class name. Why not just “CJuiWidget”? It’s more natural, because all Jui widgets extend from it. So it’s only logical to expect shared configuration in the base widget. And there’s no danger of conflict, because that class is defined abstract.

Thanks Mike,

I overlooked the fact CJuiWidget is abstract this time, because in my previous (too expensive) "inheritance" approach I already added it to my widgetFactory config (inheritance chain: CWidget, CJuiWidget, CJui…, EJui…, …).

I will go for CJuiWidget.

/Tommy

any news? i’m trying to extend cjuiwidget because i want to have the themeUrl property starting from Yii::app()->baseUrl

When you instead of this:


if (isset($this->widgets[$commonProperties]) && strpos($widgetName,$applyTo)===0)

write this:


if (isset($this->widgets[$commonProperties]) && is_subclass_of($widgetName, $commonProperties))

then you can set default settings for all classes, that are subclasses of CJuiWidget

P.S. you can also erase this string:


$applyTo='CJui';

Thanks to share