1
0

Added new (clean) yii boilerplate

This commit is contained in:
2014-05-13 12:40:42 +02:00
parent 1d6d975a16
commit 99d29b432b
1983 changed files with 653465 additions and 17 deletions

View File

@@ -0,0 +1,293 @@
<?php
/**
* CBaseListView class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CBaseListView is the base class for {@link CListView} and {@link CGridView}.
*
* CBaseListView implements the common features needed by a view wiget for rendering multiple models.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets
* @since 1.1
*/
abstract class CBaseListView extends CWidget
{
/**
* @var IDataProvider the data provider for the view.
*/
public $dataProvider;
/**
* @var string the tag name for the view container. Defaults to 'div'.
*/
public $tagName='div';
/**
* @var array the HTML options for the view container tag.
*/
public $htmlOptions=array();
/**
* @var boolean whether to enable sorting. Note that if the {@link IDataProvider::sort} property
* of {@link dataProvider} is false, this will be treated as false as well. When sorting is enabled,
* sortable columns will have their headers clickable to trigger sorting along that column.
* Defaults to true.
* @see sortableAttributes
*/
public $enableSorting=true;
/**
* @var boolean whether to enable pagination. Note that if the {@link IDataProvider::pagination} property
* of {@link dataProvider} is false, this will be treated as false as well. When pagination is enabled,
* a pager will be displayed in the view so that it can trigger pagination of the data display.
* Defaults to true.
*/
public $enablePagination=true;
/**
* @var array|string the configuration for the pager. Defaults to <code>array('class'=>'CLinkPager')</code>.
* String value will be treated as the class name of the pager (<code>'ClassName'</code> value is similar
* to the <code>array('class'=>'ClassName')</code> value). See {@link CBasePager} and {@link CLinkPager}
* for more details about pager configuration array values.
* @see enablePagination
*/
public $pager=array('class'=>'CLinkPager');
/**
* @var string the template to be used to control the layout of various sections in the view.
* These tokens are recognized: {summary}, {items} and {pager}. They will be replaced with the
* summary text, the items, and the pager.
*/
public $template="{summary}\n{items}\n{pager}";
/**
* @var string the summary text template for the view. These tokens are recognized and will be replaced
* with the corresponding values:
* <ul>
* <li>{start}: the starting row number (1-based) currently being displayed</li>
* <li>{end}: the ending row number (1-based) currently being displayed</li>
* <li>{count}: the total number of rows</li>
* <li>{page}: the page number (1-based) current being displayed, available since version 1.1.3</li>
* <li>{pages}: the total number of pages, available since version 1.1.3</li>
* </ul>
*/
public $summaryText;
/**
* @var string the message to be displayed when {@link dataProvider} does not have any data.
*/
public $emptyText;
/**
* @var string the HTML tag name for the container of the {@link emptyText} property.
*/
public $emptyTagName='span';
/**
* @var string the CSS class name for the container of all data item display. Defaults to 'items'.
*/
public $itemsCssClass='items';
/**
* @var string the CSS class name for the summary text container. Defaults to 'summary'.
*/
public $summaryCssClass='summary';
/**
* @var string the CSS class name for the pager container. Defaults to 'pager'.
*/
public $pagerCssClass='pager';
/**
* @var string the CSS class name that will be assigned to the widget container element
* when the widget is updating its content via AJAX. Defaults to 'loading'.
* @since 1.1.1
*/
public $loadingCssClass='loading';
/**
* Initializes the view.
* This method will initialize required property values and instantiate {@link columns} objects.
*/
public function init()
{
if($this->dataProvider===null)
throw new CException(Yii::t('zii','The "dataProvider" property cannot be empty.'));
$this->dataProvider->getData();
if(isset($this->htmlOptions['id']))
$this->id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$this->id;
if($this->enableSorting && $this->dataProvider->getSort()===false)
$this->enableSorting=false;
if($this->enablePagination && $this->dataProvider->getPagination()===false)
$this->enablePagination=false;
}
/**
* Renders the view.
* This is the main entry of the whole view rendering.
* Child classes should mainly override {@link renderContent} method.
*/
public function run()
{
$this->registerClientScript();
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
$this->renderContent();
$this->renderKeys();
echo CHtml::closeTag($this->tagName);
}
/**
* Renders the main content of the view.
* The content is divided into sections, such as summary, items, pager.
* Each section is rendered by a method named as "renderXyz", where "Xyz" is the section name.
* The rendering results will replace the corresponding placeholders in {@link template}.
*/
public function renderContent()
{
ob_start();
echo preg_replace_callback("/{(\w+)}/",array($this,'renderSection'),$this->template);
ob_end_flush();
}
/**
* Renders a section.
* This method is invoked by {@link renderContent} for every placeholder found in {@link template}.
* It should return the rendering result that would replace the placeholder.
* @param array $matches the matches, where $matches[0] represents the whole placeholder,
* while $matches[1] contains the name of the matched placeholder.
* @return string the rendering result of the section
*/
protected function renderSection($matches)
{
$method='render'.$matches[1];
if(method_exists($this,$method))
{
$this->$method();
$html=ob_get_contents();
ob_clean();
return $html;
}
else
return $matches[0];
}
/**
* Renders the empty message when there is no data.
*/
public function renderEmptyText()
{
$emptyText=$this->emptyText===null ? Yii::t('zii','No results found.') : $this->emptyText;
echo CHtml::tag($this->emptyTagName, array('class'=>'empty'), $emptyText);
}
/**
* Renders the key values of the data in a hidden tag.
*/
public function renderKeys()
{
echo CHtml::openTag('div',array(
'class'=>'keys',
'style'=>'display:none',
'title'=>Yii::app()->getRequest()->getUrl(),
));
foreach($this->dataProvider->getKeys() as $key)
echo "<span>".CHtml::encode($key)."</span>";
echo "</div>\n";
}
/**
* Renders the summary text.
*/
public function renderSummary()
{
if(($count=$this->dataProvider->getItemCount())<=0)
return;
echo '<div class="'.$this->summaryCssClass.'">';
if($this->enablePagination)
{
$pagination=$this->dataProvider->getPagination();
$total=$this->dataProvider->getTotalItemCount();
$start=$pagination->currentPage*$pagination->pageSize+1;
$end=$start+$count-1;
if($end>$total)
{
$end=$total;
$start=$end-$count+1;
}
if(($summaryText=$this->summaryText)===null)
$summaryText=Yii::t('zii','Displaying {start}-{end} of 1 result.|Displaying {start}-{end} of {count} results.',$total);
echo strtr($summaryText,array(
'{start}'=>$start,
'{end}'=>$end,
'{count}'=>$total,
'{page}'=>$pagination->currentPage+1,
'{pages}'=>$pagination->pageCount,
));
}
else
{
if(($summaryText=$this->summaryText)===null)
$summaryText=Yii::t('zii','Total 1 result.|Total {count} results.',$count);
echo strtr($summaryText,array(
'{count}'=>$count,
'{start}'=>1,
'{end}'=>$count,
'{page}'=>1,
'{pages}'=>1,
));
}
echo '</div>';
}
/**
* Renders the pager.
*/
public function renderPager()
{
if(!$this->enablePagination)
return;
$pager=array();
$class='CLinkPager';
if(is_string($this->pager))
$class=$this->pager;
elseif(is_array($this->pager))
{
$pager=$this->pager;
if(isset($pager['class']))
{
$class=$pager['class'];
unset($pager['class']);
}
}
$pager['pages']=$this->dataProvider->getPagination();
if($pager['pages']->getPageCount()>1)
{
echo '<div class="'.$this->pagerCssClass.'">';
$this->widget($class,$pager);
echo '</div>';
}
else
$this->widget($class,$pager);
}
/**
* Registers necessary client scripts.
* This method is invoked by {@link run}.
* Child classes may override this method to register customized client scripts.
*/
public function registerClientScript()
{
}
/**
* Renders the data items for the view.
* Each item is corresponding to a single data model instance.
* Child classes should override this method to provide the actual item rendering logic.
*/
abstract public function renderItems();
}

View File

@@ -0,0 +1,132 @@
<?php
/**
* CBreadcrumbs class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CBreadcrumbs displays a list of links indicating the position of the current page in the whole website.
*
* For example, breadcrumbs like "Home > Sample Post > Edit" means the user is viewing an edit page
* for the "Sample Post". He can click on "Sample Post" to view that page, or he can click on "Home"
* to return to the homepage.
*
* To use CBreadcrumbs, one usually needs to configure its {@link links} property, which specifies
* the links to be displayed. For example,
*
* <pre>
* $this->widget('zii.widgets.CBreadcrumbs', array(
* 'links'=>array(
* 'Sample post'=>array('post/view', 'id'=>12),
* 'Edit',
* ),
* ));
* </pre>
*
* Because breadcrumbs usually appears in nearly every page of a website, the widget is better to be placed
* in a layout view. One can define a property "breadcrumbs" in the base controller class and assign it to the widget
* in the layout, like the following:
*
* <pre>
* $this->widget('zii.widgets.CBreadcrumbs', array(
* 'links'=>$this->breadcrumbs,
* ));
* </pre>
*
* Then, in each view script, one only needs to assign the "breadcrumbs" property as needed.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets
* @since 1.1
*/
class CBreadcrumbs extends CWidget
{
/**
* @var string the tag name for the breadcrumbs container tag. Defaults to 'div'.
*/
public $tagName='div';
/**
* @var array the HTML attributes for the breadcrumbs container tag.
*/
public $htmlOptions=array('class'=>'breadcrumbs');
/**
* @var boolean whether to HTML encode the link labels. Defaults to true.
*/
public $encodeLabel=true;
/**
* @var string the first hyperlink in the breadcrumbs (called home link).
* If this property is not set, it defaults to a link pointing to {@link CWebApplication::homeUrl} with label 'Home'.
* If this property is false, the home link will not be rendered.
*/
public $homeLink;
/**
* @var array list of hyperlinks to appear in the breadcrumbs. If this property is empty,
* the widget will not render anything. Each key-value pair in the array
* will be used to generate a hyperlink by calling CHtml::link(key, value). For this reason, the key
* refers to the label of the link while the value can be a string or an array (used to
* create a URL). For more details, please refer to {@link CHtml::link}.
* If an element's key is an integer, it means the element will be rendered as a label only (meaning the current page).
*
* The following example will generate breadcrumbs as "Home > Sample post > Edit", where "Home" points to the homepage,
* "Sample post" points to the "index.php?r=post/view&id=12" page, and "Edit" is a label. Note that the "Home" link
* is specified via {@link homeLink} separately.
*
* <pre>
* array(
* 'Sample post'=>array('post/view', 'id'=>12),
* 'Edit',
* )
* </pre>
*/
public $links=array();
/**
* @var string String, specifies how each active item is rendered. Defaults to
* "<a href="{url}">{label}</a>", where "{label}" will be replaced by the corresponding item
* label while "{url}" will be replaced by the URL of the item.
* @since 1.1.11
*/
public $activeLinkTemplate='<a href="{url}">{label}</a>';
/**
* @var string String, specifies how each inactive item is rendered. Defaults to
* "<span>{label}</span>", where "{label}" will be replaced by the corresponding item label.
* Note that inactive template does not have "{url}" parameter.
* @since 1.1.11
*/
public $inactiveLinkTemplate='<span>{label}</span>';
/**
* @var string the separator between links in the breadcrumbs. Defaults to ' &raquo; '.
*/
public $separator=' &raquo; ';
/**
* Renders the content of the portlet.
*/
public function run()
{
if(empty($this->links))
return;
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
$links=array();
if($this->homeLink===null)
$links[]=CHtml::link(Yii::t('zii','Home'),Yii::app()->homeUrl);
elseif($this->homeLink!==false)
$links[]=$this->homeLink;
foreach($this->links as $label=>$url)
{
if(is_string($label) || is_array($url))
$links[]=strtr($this->activeLinkTemplate,array(
'{url}'=>CHtml::normalizeUrl($url),
'{label}'=>$this->encodeLabel ? CHtml::encode($label) : $label,
));
else
$links[]=str_replace('{label}',$this->encodeLabel ? CHtml::encode($url) : $url,$this->inactiveLinkTemplate);
}
echo implode($this->separator,$links);
echo CHtml::closeTag($this->tagName);
}
}

View File

@@ -0,0 +1,258 @@
<?php
/**
* CDetailView class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CDetailView displays the detail of a single data model.
*
* CDetailView is best used for displaying a model in a regular format (e.g. each model attribute
* is displayed as a row in a table.) The model can be either an instance of {@link CModel}
* or an associative array.
*
* CDetailView uses the {@link attributes} property to determines which model attributes
* should be displayed and how they should be formatted.
*
* A typical usage of CDetailView is as follows:
* <pre>
* $this->widget('zii.widgets.CDetailView', array(
* 'data'=>$model,
* 'attributes'=>array(
* 'title', // title attribute (in plain text)
* 'owner.name', // an attribute of the related object "owner"
* 'description:html', // description attribute in HTML
* array( // related city displayed as a link
* 'label'=>'City',
* 'type'=>'raw',
* 'value'=>CHtml::link(CHtml::encode($model->city->name),
* array('city/view','id'=>$model->city->id)),
* ),
* ),
* ));
* </pre>
*
* @property CFormatter $formatter The formatter instance. Defaults to the 'format' application component.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets
* @since 1.1
*/
class CDetailView extends CWidget
{
private $_formatter;
/**
* @var mixed the data model whose details are to be displayed. This can be either a {@link CModel} instance
* (e.g. a {@link CActiveRecord} object or a {@link CFormModel} object) or an associative array.
*/
public $data;
/**
* @var array a list of attributes to be displayed in the detail view. Each array element
* represents the specification for displaying one particular attribute.
*
* An attribute can be specified as a string in the format of "Name:Type:Label".
* Both "Type" and "Label" are optional.
*
* "Name" refers to the attribute name. It can be either a property (e.g. "title") or a sub-property (e.g. "owner.username").
*
* "Label" represents the label for the attribute display. If it is not given, "Name" will be used to generate the appropriate label.
*
* "Type" represents the type of the attribute. It determines how the attribute value should be formatted and displayed.
* It is defaulted to be 'text'.
* "Type" should be recognizable by the {@link formatter}. In particular, if "Type" is "xyz", then the "formatXyz" method
* of {@link formatter} will be invoked to format the attribute value for display. By default when {@link CFormatter} is used,
* these "Type" values are valid: raw, text, ntext, html, date, time, datetime, boolean, number, email, image, url.
* For more details about these types, please refer to {@link CFormatter}.
*
* An attribute can also be specified in terms of an array with the following elements:
* <ul>
* <li>label: the label associated with the attribute. If this is not specified, the following "name" element
* will be used to generate an appropriate label.</li>
* <li>name: the name of the attribute. This can be either a property or a sub-property of the model.
* If the below "value" element is specified, this will be ignored.</li>
* <li>value: the value to be displayed. If this is not specified, the above "name" element will be used
* to retrieve the corresponding attribute value for display. Note that this value will be formatted according
* to the "type" option as described below.</li>
* <li>type: the type of the attribute that determines how the attribute value would be formatted.
* Please see above for possible values.
* <li>cssClass: the CSS class to be used for this item. This option is available since version 1.1.3.</li>
* <li>template: the template used to render the attribute. If this is not specified, {@link itemTemplate}
* will be used instead. For more details on how to set this option, please refer to {@link itemTemplate}.
* This option is available since version 1.1.1.</li>
* <li>visible: whether the attribute is visible. If set to <code>false</code>, the table row for the attribute will not be rendered.
* This option is available since version 1.1.5.</li>
* </ul>
*/
public $attributes;
/**
* @var string the text to be displayed when an attribute value is null. Defaults to "Not set".
*/
public $nullDisplay;
/**
* @var string the name of the tag for rendering the detail view. Defaults to 'table'.
* If set to null, no tag will be rendered.
* @see itemTemplate
*/
public $tagName='table';
/**
* @var string the template used to render a single attribute. Defaults to a table row.
* These tokens are recognized: "{class}", "{label}" and "{value}". They will be replaced
* with the CSS class name for the item, the label and the attribute value, respectively.
* @see itemCssClass
*/
public $itemTemplate="<tr class=\"{class}\"><th>{label}</th><td>{value}</td></tr>\n";
/**
* @var array the CSS class names for the items displaying attribute values. If multiple CSS class names are given,
* they will be assigned to the items sequentially and repeatedly.
* Defaults to <code>array('odd', 'even')</code>.
*/
public $itemCssClass=array('odd','even');
/**
* @var array the HTML options used for {@link tagName}
*/
public $htmlOptions=array('class'=>'detail-view');
/**
* @var string the base script URL for all detail view resources (e.g. javascript, CSS file, images).
* Defaults to null, meaning using the integrated detail view resources (which are published as assets).
*/
public $baseScriptUrl;
/**
* @var string the URL of the CSS file used by this detail view. Defaults to null, meaning using the integrated
* CSS file. If this is set false, you are responsible to explicitly include the necessary CSS file in your page.
*/
public $cssFile;
/**
* Initializes the detail view.
* This method will initialize required property values.
*/
public function init()
{
if($this->data===null)
throw new CException(Yii::t('zii','Please specify the "data" property.'));
if($this->attributes===null)
{
if($this->data instanceof CModel)
$this->attributes=$this->data->attributeNames();
elseif(is_array($this->data))
$this->attributes=array_keys($this->data);
else
throw new CException(Yii::t('zii','Please specify the "attributes" property.'));
}
if($this->nullDisplay===null)
$this->nullDisplay='<span class="null">'.Yii::t('zii','Not set').'</span>';
if(isset($this->htmlOptions['id']))
$this->id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$this->id;
if($this->baseScriptUrl===null)
$this->baseScriptUrl=Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('zii.widgets.assets')).'/detailview';
if($this->cssFile!==false)
{
if($this->cssFile===null)
$this->cssFile=$this->baseScriptUrl.'/styles.css';
Yii::app()->getClientScript()->registerCssFile($this->cssFile);
}
}
/**
* Renders the detail view.
* This is the main entry of the whole detail view rendering.
*/
public function run()
{
$formatter=$this->getFormatter();
if ($this->tagName!==null)
echo CHtml::openTag($this->tagName,$this->htmlOptions);
$i=0;
$n=is_array($this->itemCssClass) ? count($this->itemCssClass) : 0;
foreach($this->attributes as $attribute)
{
if(is_string($attribute))
{
if(!preg_match('/^([\w\.]+)(:(\w*))?(:(.*))?$/',$attribute,$matches))
throw new CException(Yii::t('zii','The attribute must be specified in the format of "Name:Type:Label", where "Type" and "Label" are optional.'));
$attribute=array(
'name'=>$matches[1],
'type'=>isset($matches[3]) ? $matches[3] : 'text',
);
if(isset($matches[5]))
$attribute['label']=$matches[5];
}
if(isset($attribute['visible']) && !$attribute['visible'])
continue;
$tr=array('{label}'=>'', '{class}'=>$n ? $this->itemCssClass[$i%$n] : '');
if(isset($attribute['cssClass']))
$tr['{class}']=$attribute['cssClass'].' '.($n ? $tr['{class}'] : '');
if(isset($attribute['label']))
$tr['{label}']=$attribute['label'];
elseif(isset($attribute['name']))
{
if($this->data instanceof CModel)
$tr['{label}']=$this->data->getAttributeLabel($attribute['name']);
else
$tr['{label}']=ucwords(trim(strtolower(str_replace(array('-','_','.'),' ',preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $attribute['name'])))));
}
if(!isset($attribute['type']))
$attribute['type']='text';
if(isset($attribute['value']))
$value=is_callable($attribute['value']) ? call_user_func($attribute['value'],$this->data) : $attribute['value'];
elseif(isset($attribute['name']))
$value=CHtml::value($this->data,$attribute['name']);
else
$value=null;
$tr['{value}']=$value===null ? $this->nullDisplay : $formatter->format($value,$attribute['type']);
$this->renderItem($attribute, $tr);
$i++;
}
if ($this->tagName!==null)
echo CHtml::closeTag($this->tagName);
}
/**
* This method is used by run() to render item row
*
* @param array $options config options for this item/attribute from {@link attributes}
* @param string $templateData data that will be inserted into {@link itemTemplate}
* @since 1.1.11
*/
protected function renderItem($options,$templateData)
{
echo strtr(isset($options['template']) ? $options['template'] : $this->itemTemplate,$templateData);
}
/**
* @return CFormatter the formatter instance. Defaults to the 'format' application component.
*/
public function getFormatter()
{
if($this->_formatter===null)
$this->_formatter=Yii::app()->format;
return $this->_formatter;
}
/**
* @param CFormatter $value the formatter instance
*/
public function setFormatter($value)
{
$this->_formatter=$value;
}
}

View File

@@ -0,0 +1,325 @@
<?php
/**
* CListView class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.CBaseListView');
/**
* CListView displays a list of data items in terms of a list.
*
* Unlike {@link CGridView} which displays the data items in a table, CListView allows one to use
* a view template to render each data item. As a result, CListView could generate more flexible
* rendering result.
*
* CListView supports both sorting and pagination of the data items. The sorting
* and pagination can be done in AJAX mode or normal page request. A benefit of using CListView is that
* when the user browser disables JavaScript, the sorting and pagination automatically degenerate
* to normal page requests and are still functioning as expected.
*
* CListView should be used together with a {@link IDataProvider data provider}, preferrably a
* {@link CActiveDataProvider}.
*
* The minimal code needed to use CListView is as follows:
*
* <pre>
* $dataProvider=new CActiveDataProvider('Post');
*
* $this->widget('zii.widgets.CListView', array(
* 'dataProvider'=>$dataProvider,
* 'itemView'=>'_post', // refers to the partial view named '_post'
* 'sortableAttributes'=>array(
* 'title',
* 'create_time'=>'Post Time',
* ),
* ));
* </pre>
*
* The above code first creates a data provider for the <code>Post</code> ActiveRecord class.
* It then uses CListView to display every data item as returned by the data provider.
* The display is done via the partial view named '_post'. This partial view will be rendered
* once for every data item. In the view, one can access the current data item via variable <code>$data</code>.
* For more details, see {@link itemView}.
*
* In order to support sorting, one has to specify the {@link sortableAttributes} property.
* By doing so, a list of hyperlinks that can sort the data will be displayed.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets
* @since 1.1
*/
class CListView extends CBaseListView
{
/**
* @var string the view used for rendering each data item.
* This property value will be passed as the first parameter to either {@link CController::renderPartial}
* or {@link CWidget::render} to render each data item.
* In the corresponding view template, the following variables can be used in addition to those declared in {@link viewData}:
* <ul>
* <li><code>$this</code>: refers to the owner of this list view widget. For example, if the widget is in the view of a controller,
* then <code>$this</code> refers to the controller.</li>
* <li><code>$data</code>: refers to the data item currently being rendered.</li>
* <li><code>$index</code>: refers to the zero-based index of the data item currently being rendered.</li>
* <li><code>$widget</code>: refers to this list view widget instance.</li>
* </ul>
*/
public $itemView;
/**
* @var string the HTML code to be displayed between any two consecutive items.
* @since 1.1.7
*/
public $separator;
/**
* @var array additional data to be passed to {@link itemView} when rendering each data item.
* This array will be extracted into local PHP variables that can be accessed in the {@link itemView}.
*/
public $viewData=array();
/**
* @var array list of sortable attribute names. In order for an attribute to be sortable, it must also
* appear as a sortable attribute in the {@link IDataProvider::sort} property of {@link dataProvider}.
* @see enableSorting
*/
public $sortableAttributes;
/**
* @var string the template to be used to control the layout of various components in the list view.
* These tokens are recognized: {summary}, {sorter}, {items} and {pager}. They will be replaced with the
* summary text, the sort links, the data item list, and the pager.
*/
public $template="{summary}\n{sorter}\n{items}\n{pager}";
/**
* @var string the CSS class name that will be assigned to the widget container element
* when the widget is updating its content via AJAX. Defaults to 'list-view-loading'.
* @since 1.1.1
*/
public $loadingCssClass='list-view-loading';
/**
* @var string the CSS class name for the sorter container. Defaults to 'sorter'.
*/
public $sorterCssClass='sorter';
/**
* @var string the text shown before sort links. Defaults to 'Sort by: '.
*/
public $sorterHeader;
/**
* @var string the text shown after sort links. Defaults to empty.
*/
public $sorterFooter='';
/**
* @var mixed the ID of the container whose content may be updated with an AJAX response.
* Defaults to null, meaning the container for this list view instance.
* If it is set false, it means sorting and pagination will be performed in normal page requests
* instead of AJAX requests. If the sorting and pagination should trigger the update of multiple
* containers' content in AJAX fashion, these container IDs may be listed here (separated with comma).
*/
public $ajaxUpdate;
/**
* @var string the jQuery selector of the HTML elements that may trigger AJAX updates when they are clicked.
* If not set, the pagination links and the sorting links will trigger AJAX updates.
* @since 1.1.7
*/
public $updateSelector;
/**
* @var string a javascript function that will be invoked if an AJAX update error occurs.
*
* The function signature is <code>function(xhr, textStatus, errorThrown, errorMessage)</code>
* <ul>
* <li><code>xhr</code> is the XMLHttpRequest object.</li>
* <li><code>textStatus</code> is a string describing the type of error that occurred.
* Possible values (besides null) are "timeout", "error", "notmodified" and "parsererror"</li>
* <li><code>errorThrown</code> is an optional exception object, if one occurred.</li>
* <li><code>errorMessage</code> is the CGridView default error message derived from xhr and errorThrown.
* Usefull if you just want to display this error differently. CGridView by default displays this error with an javascript.alert()</li>
* </ul>
* Note: This handler is not called for JSONP requests, because they do not use an XMLHttpRequest.
*
* Example (add in a call to CGridView):
* <pre>
* ...
* 'ajaxUpdateError'=>'function(xhr,ts,et,err){ $("#myerrordiv").text(err); }',
* ...
* </pre>
* @since 1.1.13
*/
public $ajaxUpdateError;
/**
* @var string the name of the GET variable that indicates the request is an AJAX request triggered
* by this widget. Defaults to 'ajax'. This is effective only when {@link ajaxUpdate} is not false.
*/
public $ajaxVar='ajax';
/**
* @var mixed the URL for the AJAX requests should be sent to. {@link CHtml::normalizeUrl()} will be
* called on this property. If not set, the current page URL will be used for AJAX requests.
* @since 1.1.8
*/
public $ajaxUrl;
/**
* @var string the type ('GET' or 'POST') of the AJAX requests. If not set, 'GET' will be used.
* You can set this to 'POST' if you are filtering by many fields at once and have a problem with GET query string length.
* Note that in POST mode direct links and {@link enableHistory} feature may not work correctly!
* @since 1.1.14
*/
public $ajaxType;
/**
* @var string a javascript function that will be invoked before an AJAX update occurs.
* The function signature is <code>function(id)</code> where 'id' refers to the ID of the list view.
*/
public $beforeAjaxUpdate;
/**
* @var string a javascript function that will be invoked after a successful AJAX response is received.
* The function signature is <code>function(id, data)</code> where 'id' refers to the ID of the list view
* 'data' the received ajax response data.
*/
public $afterAjaxUpdate;
/**
* @var string the base script URL for all list view resources (e.g. javascript, CSS file, images).
* Defaults to null, meaning using the integrated list view resources (which are published as assets).
*/
public $baseScriptUrl;
/**
* @var string the URL of the CSS file used by this list view. Defaults to null, meaning using the integrated
* CSS file. If this is set false, you are responsible to explicitly include the necessary CSS file in your page.
*/
public $cssFile;
/**
* @var string the HTML tag name for the container of all data item display. Defaults to 'div'.
* @since 1.1.4
*/
public $itemsTagName='div';
/**
* @var boolean whether to leverage the {@link https://developer.mozilla.org/en/DOM/window.history DOM history object}. Set this property to true
* to persist state of list across page revisits. Note, there are two limitations for this feature:
* - this feature is only compatible with browsers that support HTML5.
* - expect unexpected functionality (e.g. multiple ajax calls) if there is more than one grid/list on a single page with enableHistory turned on.
* @since 1.1.11
*/
public $enableHistory=false;
/**
* Initializes the list view.
* This method will initialize required property values and instantiate {@link columns} objects.
*/
public function init()
{
if($this->itemView===null)
throw new CException(Yii::t('zii','The property "itemView" cannot be empty.'));
parent::init();
if(!isset($this->htmlOptions['class']))
$this->htmlOptions['class']='list-view';
if($this->baseScriptUrl===null)
$this->baseScriptUrl=Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('zii.widgets.assets')).'/listview';
if($this->cssFile!==false)
{
if($this->cssFile===null)
$this->cssFile=$this->baseScriptUrl.'/styles.css';
Yii::app()->getClientScript()->registerCssFile($this->cssFile);
}
}
/**
* Registers necessary client scripts.
*/
public function registerClientScript()
{
$id=$this->getId();
if($this->ajaxUpdate===false)
$ajaxUpdate=array();
else
$ajaxUpdate=array_unique(preg_split('/\s*,\s*/',$this->ajaxUpdate.','.$id,-1,PREG_SPLIT_NO_EMPTY));
$options=array(
'ajaxUpdate'=>$ajaxUpdate,
'ajaxVar'=>$this->ajaxVar,
'pagerClass'=>$this->pagerCssClass,
'loadingClass'=>$this->loadingCssClass,
'sorterClass'=>$this->sorterCssClass,
'enableHistory'=>$this->enableHistory
);
if($this->ajaxUrl!==null)
$options['url']=CHtml::normalizeUrl($this->ajaxUrl);
if($this->ajaxType!==null)
$options['ajaxType']=strtoupper($this->ajaxType);
if($this->updateSelector!==null)
$options['updateSelector']=$this->updateSelector;
foreach(array('beforeAjaxUpdate', 'afterAjaxUpdate', 'ajaxUpdateError') as $event)
{
if($this->$event!==null)
{
if($this->$event instanceof CJavaScriptExpression)
$options[$event]=$this->$event;
else
$options[$event]=new CJavaScriptExpression($this->$event);
}
}
$options=CJavaScript::encode($options);
$cs=Yii::app()->getClientScript();
$cs->registerCoreScript('jquery');
$cs->registerCoreScript('bbq');
if($this->enableHistory)
$cs->registerCoreScript('history');
$cs->registerScriptFile($this->baseScriptUrl.'/jquery.yiilistview.js',CClientScript::POS_END);
$cs->registerScript(__CLASS__.'#'.$id,"jQuery('#$id').yiiListView($options);");
}
/**
* Renders the data item list.
*/
public function renderItems()
{
echo CHtml::openTag($this->itemsTagName,array('class'=>$this->itemsCssClass))."\n";
$data=$this->dataProvider->getData();
if(($n=count($data))>0)
{
$owner=$this->getOwner();
$viewFile=$owner->getViewFile($this->itemView);
$j=0;
foreach($data as $i=>$item)
{
$data=$this->viewData;
$data['index']=$i;
$data['data']=$item;
$data['widget']=$this;
$owner->renderFile($viewFile,$data);
if($j++ < $n-1)
echo $this->separator;
}
}
else
$this->renderEmptyText();
echo CHtml::closeTag($this->itemsTagName);
}
/**
* Renders the sorter.
*/
public function renderSorter()
{
if($this->dataProvider->getItemCount()<=0 || !$this->enableSorting || empty($this->sortableAttributes))
return;
echo CHtml::openTag('div',array('class'=>$this->sorterCssClass))."\n";
echo $this->sorterHeader===null ? Yii::t('zii','Sort by: ') : $this->sorterHeader;
echo "<ul>\n";
$sort=$this->dataProvider->getSort();
foreach($this->sortableAttributes as $name=>$label)
{
echo "<li>";
if(is_integer($name))
echo $sort->link($label);
else
echo $sort->link($name,$label);
echo "</li>\n";
}
echo "</ul>";
echo $this->sorterFooter;
echo CHtml::closeTag('div');
}
}

View File

@@ -0,0 +1,326 @@
<?php
/**
* CMenu class file.
*
* @author Jonah Turnquist <poppitypop@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CMenu displays a multi-level menu using nested HTML lists.
*
* The main property of CMenu is {@link items}, which specifies the possible items in the menu.
* A menu item has three main properties: visible, active and items. The "visible" property
* specifies whether the menu item is currently visible. The "active" property specifies whether
* the menu item is currently selected. And the "items" property specifies the child menu items.
*
* The following example shows how to use CMenu:
* <pre>
* $this->widget('zii.widgets.CMenu', array(
* 'items'=>array(
* // Important: you need to specify url as 'controller/action',
* // not just as 'controller' even if default acion is used.
* array('label'=>'Home', 'url'=>array('site/index')),
* // 'Products' menu item will be selected no matter which tag parameter value is since it's not specified.
* array('label'=>'Products', 'url'=>array('product/index'), 'items'=>array(
* array('label'=>'New Arrivals', 'url'=>array('product/new', 'tag'=>'new')),
* array('label'=>'Most Popular', 'url'=>array('product/index', 'tag'=>'popular')),
* )),
* array('label'=>'Login', 'url'=>array('site/login'), 'visible'=>Yii::app()->user->isGuest),
* ),
* ));
* </pre>
*
*
* @author Jonah Turnquist <poppitypop@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets
* @since 1.1
*/
class CMenu extends CWidget
{
/**
* @var array list of menu items. Each menu item is specified as an array of name-value pairs.
* Possible option names include the following:
* <ul>
* <li>label: string, optional, specifies the menu item label. When {@link encodeLabel} is true, the label
* will be HTML-encoded. If the label is not specified, it defaults to an empty string.</li>
* <li>url: string or array, optional, specifies the URL of the menu item. It is passed to {@link CHtml::normalizeUrl}
* to generate a valid URL. If this is not set, the menu item will be rendered as a span text.</li>
* <li>visible: boolean, optional, whether this menu item is visible. Defaults to true.
* This can be used to control the visibility of menu items based on user permissions.</li>
* <li>items: array, optional, specifies the sub-menu items. Its format is the same as the parent items.</li>
* <li>active: boolean, optional, whether this menu item is in active state (currently selected).
* If a menu item is active and {@link activeClass} is not empty, its CSS class will be appended with {@link activeClass}.
* If this option is not set, the menu item will be set active automatically when the current request
* is triggered by {@link url}. Note that the GET parameters not specified in the 'url' option will be ignored.</li>
* <li>template: string, optional, the template used to render this menu item.
* When this option is set, it will override the global setting {@link itemTemplate}.
* Please see {@link itemTemplate} for more details. This option has been available since version 1.1.1.</li>
* <li>linkOptions: array, optional, additional HTML attributes to be rendered for the link or span tag of the menu item.</li>
* <li>itemOptions: array, optional, additional HTML attributes to be rendered for the container tag of the menu item.</li>
* <li>submenuOptions: array, optional, additional HTML attributes to be rendered for the container of the submenu if this menu item has one.
* When this option is set, the {@link submenuHtmlOptions} property will be ignored for this particular submenu.
* This option has been available since version 1.1.6.</li>
* </ul>
*/
public $items=array();
/**
* @var string the template used to render an individual menu item. In this template,
* the token "{menu}" will be replaced with the corresponding menu link or text.
* If this property is not set, each menu will be rendered without any decoration.
* This property will be overridden by the 'template' option set in individual menu items via {@items}.
* @since 1.1.1
*/
public $itemTemplate;
/**
* @var boolean whether the labels for menu items should be HTML-encoded. Defaults to true.
*/
public $encodeLabel=true;
/**
* @var string the CSS class to be appended to the active menu item. Defaults to 'active'.
* If empty, the CSS class of menu items will not be changed.
*/
public $activeCssClass='active';
/**
* @var boolean whether to automatically activate items according to whether their route setting
* matches the currently requested route. Defaults to true.
* @since 1.1.3
*/
public $activateItems=true;
/**
* @var boolean whether to activate parent menu items when one of the corresponding child menu items is active.
* The activated parent menu items will also have its CSS classes appended with {@link activeCssClass}.
* Defaults to false.
*/
public $activateParents=false;
/**
* @var boolean whether to hide empty menu items. An empty menu item is one whose 'url' option is not
* set and which doesn't contain visible child menu items. Defaults to true.
*/
public $hideEmptyItems=true;
/**
* @var array HTML attributes for the menu's root container tag
*/
public $htmlOptions=array();
/**
* @var array HTML attributes for the submenu's container tag.
*/
public $submenuHtmlOptions=array();
/**
* @var string the HTML element name that will be used to wrap the label of all menu links.
* For example, if this property is set as 'span', a menu item may be rendered as
* &lt;li&gt;&lt;a href="url"&gt;&lt;span&gt;label&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
* This is useful when implementing menu items using the sliding window technique.
* Defaults to null, meaning no wrapper tag will be generated.
* @since 1.1.4
*/
public $linkLabelWrapper;
/**
* @var array HTML attributes for the links' wrap element specified in
* {@link linkLabelWrapper}.
* @since 1.1.13
*/
public $linkLabelWrapperHtmlOptions=array();
/**
* @var string the CSS class that will be assigned to the first item in the main menu or each submenu.
* Defaults to null, meaning no such CSS class will be assigned.
* @since 1.1.4
*/
public $firstItemCssClass;
/**
* @var string the CSS class that will be assigned to the last item in the main menu or each submenu.
* Defaults to null, meaning no such CSS class will be assigned.
* @since 1.1.4
*/
public $lastItemCssClass;
/**
* @var string the CSS class that will be assigned to every item.
* Defaults to null, meaning no such CSS class will be assigned.
* @since 1.1.9
*/
public $itemCssClass;
/**
* Initializes the menu widget.
* This method mainly normalizes the {@link items} property.
* If this method is overridden, make sure the parent implementation is invoked.
*/
public function init()
{
if(isset($this->htmlOptions['id']))
$this->id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$this->id;
$route=$this->getController()->getRoute();
$this->items=$this->normalizeItems($this->items,$route,$hasActiveChild);
}
/**
* Calls {@link renderMenu} to render the menu.
*/
public function run()
{
$this->renderMenu($this->items);
}
/**
* Renders the menu items.
* @param array $items menu items. Each menu item will be an array with at least two elements: 'label' and 'active'.
* It may have three other optional elements: 'items', 'linkOptions' and 'itemOptions'.
*/
protected function renderMenu($items)
{
if(count($items))
{
echo CHtml::openTag('ul',$this->htmlOptions)."\n";
$this->renderMenuRecursive($items);
echo CHtml::closeTag('ul');
}
}
/**
* Recursively renders the menu items.
* @param array $items the menu items to be rendered recursively
*/
protected function renderMenuRecursive($items)
{
$count=0;
$n=count($items);
foreach($items as $item)
{
$count++;
$options=isset($item['itemOptions']) ? $item['itemOptions'] : array();
$class=array();
if($item['active'] && $this->activeCssClass!='')
$class[]=$this->activeCssClass;
if($count===1 && $this->firstItemCssClass!==null)
$class[]=$this->firstItemCssClass;
if($count===$n && $this->lastItemCssClass!==null)
$class[]=$this->lastItemCssClass;
if($this->itemCssClass!==null)
$class[]=$this->itemCssClass;
if($class!==array())
{
if(empty($options['class']))
$options['class']=implode(' ',$class);
else
$options['class'].=' '.implode(' ',$class);
}
echo CHtml::openTag('li', $options);
$menu=$this->renderMenuItem($item);
if(isset($this->itemTemplate) || isset($item['template']))
{
$template=isset($item['template']) ? $item['template'] : $this->itemTemplate;
echo strtr($template,array('{menu}'=>$menu));
}
else
echo $menu;
if(isset($item['items']) && count($item['items']))
{
echo "\n".CHtml::openTag('ul',isset($item['submenuOptions']) ? $item['submenuOptions'] : $this->submenuHtmlOptions)."\n";
$this->renderMenuRecursive($item['items']);
echo CHtml::closeTag('ul')."\n";
}
echo CHtml::closeTag('li')."\n";
}
}
/**
* Renders the content of a menu item.
* Note that the container and the sub-menus are not rendered here.
* @param array $item the menu item to be rendered. Please see {@link items} on what data might be in the item.
* @return string
* @since 1.1.6
*/
protected function renderMenuItem($item)
{
if(isset($item['url']))
{
$label=$this->linkLabelWrapper===null ? $item['label'] : CHtml::tag($this->linkLabelWrapper, $this->linkLabelWrapperHtmlOptions, $item['label']);
return CHtml::link($label,$item['url'],isset($item['linkOptions']) ? $item['linkOptions'] : array());
}
else
return CHtml::tag('span',isset($item['linkOptions']) ? $item['linkOptions'] : array(), $item['label']);
}
/**
* Normalizes the {@link items} property so that the 'active' state is properly identified for every menu item.
* @param array $items the items to be normalized.
* @param string $route the route of the current request.
* @param boolean $active whether there is an active child menu item.
* @return array the normalized menu items
*/
protected function normalizeItems($items,$route,&$active)
{
foreach($items as $i=>$item)
{
if(isset($item['visible']) && !$item['visible'])
{
unset($items[$i]);
continue;
}
if(!isset($item['label']))
$item['label']='';
if($this->encodeLabel)
$items[$i]['label']=CHtml::encode($item['label']);
$hasActiveChild=false;
if(isset($item['items']))
{
$items[$i]['items']=$this->normalizeItems($item['items'],$route,$hasActiveChild);
if(empty($items[$i]['items']) && $this->hideEmptyItems)
{
unset($items[$i]['items']);
if(!isset($item['url']))
{
unset($items[$i]);
continue;
}
}
}
if(!isset($item['active']))
{
if($this->activateParents && $hasActiveChild || $this->activateItems && $this->isItemActive($item,$route))
$active=$items[$i]['active']=true;
else
$items[$i]['active']=false;
}
elseif($item['active'])
$active=true;
}
return array_values($items);
}
/**
* Checks whether a menu item is active.
* This is done by checking if the currently requested URL is generated by the 'url' option
* of the menu item. Note that the GET parameters not specified in the 'url' option will be ignored.
* @param array $item the menu item to be checked
* @param string $route the route of the current request
* @return boolean whether the menu item is active
*/
protected function isItemActive($item,$route)
{
if(isset($item['url']) && is_array($item['url']) && !strcasecmp(trim($item['url'][0],'/'),$route))
{
unset($item['url']['#']);
if(count($item['url'])>1)
{
foreach(array_splice($item['url'],1) as $name=>$value)
{
if(!isset($_GET[$name]) || $_GET[$name]!=$value)
return false;
}
}
return true;
}
return false;
}
}

View File

@@ -0,0 +1,128 @@
<?php
/**
* CPortlet class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CPortlet is the base class for portlet widgets.
*
* A portlet displays a fragment of content, usually in terms of a block
* on the side bars of a Web page.
*
* To specify the content of the portlet, override the {@link renderContent}
* method, or insert the content code between the {@link CController::beginWidget}
* and {@link CController::endWidget} calls. For example,
*
* <pre>
* <?php $this->beginWidget('zii.widgets.CPortlet'); ?>
* ...insert content here...
* <?php $this->endWidget(); ?>
* </pre>
*
* A portlet also has an optional {@link title}. One may also override {@link renderDecoration}
* to further customize the decorative display of a portlet (e.g. adding min/max buttons).
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets
* @since 1.1
*/
class CPortlet extends CWidget
{
/**
* @var string the tag name for the portlet container tag. Defaults to 'div'.
*/
public $tagName='div';
/**
* @var array the HTML attributes for the portlet container tag.
*/
public $htmlOptions=array('class'=>'portlet');
/**
* @var string the title of the portlet. Defaults to null.
* When this is not set, Decoration will not be displayed.
* Note that the title will not be HTML-encoded when rendering.
*/
public $title;
/**
* @var string the CSS class for the decoration container tag. Defaults to 'portlet-decoration'.
*/
public $decorationCssClass='portlet-decoration';
/**
* @var string the CSS class for the portlet title tag. Defaults to 'portlet-title'.
*/
public $titleCssClass='portlet-title';
/**
* @var string the CSS class for the content container tag. Defaults to 'portlet-content'.
*/
public $contentCssClass='portlet-content';
/**
* @var boolean whether to hide the portlet when the body content is empty. Defaults to true.
* @since 1.1.4
*/
public $hideOnEmpty=true;
private $_openTag;
/**
* Initializes the widget.
* This renders the open tags needed by the portlet.
* It also renders the decoration, if any.
*/
public function init()
{
ob_start();
ob_implicit_flush(false);
if(isset($this->htmlOptions['id']))
$this->id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$this->id;
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
$this->renderDecoration();
echo "<div class=\"{$this->contentCssClass}\">\n";
$this->_openTag=ob_get_contents();
ob_clean();
}
/**
* Renders the content of the portlet.
*/
public function run()
{
$this->renderContent();
$content=ob_get_clean();
if($this->hideOnEmpty && trim($content)==='')
return;
echo $this->_openTag;
echo $content;
echo "</div>\n";
echo CHtml::closeTag($this->tagName);
}
/**
* Renders the decoration for the portlet.
* The default implementation will render the title if it is set.
*/
protected function renderDecoration()
{
if($this->title!==null)
{
echo "<div class=\"{$this->decorationCssClass}\">\n";
echo "<div class=\"{$this->titleCssClass}\">{$this->title}</div>\n";
echo "</div>\n";
}
}
/**
* Renders the content of the portlet.
* Child classes should override this method to render the actual content.
*/
protected function renderContent()
{
}
}

View File

@@ -0,0 +1,44 @@
table.detail-view .null
{
color: pink;
}
table.detail-view
{
background: white;
border-collapse: collapse;
width: 100%;
margin: 0;
}
table.detail-view th, table.detail-view td
{
font-size: 0.9em;
border: 1px white solid;
padding: 0.3em 0.6em;
vertical-align: top;
}
table.detail-view th
{
text-align: right;
width: 160px;
}
table.detail-view tr.odd
{
background:#E5F1F4;
}
table.detail-view tr.even
{
background:#F8F8F8;
}
table.detail-view tr.odd th
{
}
table.detail-view tr.even th
{
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 715 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 B

View File

@@ -0,0 +1,475 @@
/**
* jQuery Yii GridView plugin file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2010 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
(function ($) {
var selectCheckedRows, methods,
yiiXHR={},
gridSettings = [];
/**
* 1. Selects rows that have checkbox checked (only checkbox that is connected with selecting a row)
* 2. Check if "check all" need to be checked/unchecked
* @return object the jQuery object
*/
selectCheckedRows = function (gridId) {
var settings = gridSettings[gridId],
table = $('#' + gridId).find('.' + settings.tableClass);
table.children('tbody').find('input.select-on-check').filter(':checked').each(function () {
$(this).closest('tr').addClass('selected');
});
table.children('thead').find('th input').filter('[type="checkbox"]').each(function () {
var name = this.name.substring(0, this.name.length - 4) + '[]', //.. remove '_all' and add '[]''
$checks = $("input[name='" + name + "']", table);
this.checked = $checks.length > 0 && $checks.length === $checks.filter(':checked').length;
});
return this;
};
methods = {
/**
* yiiGridView set function.
* @param options map settings for the grid view. Available options are as follows:
* - ajaxUpdate: array, IDs of the containers whose content may be updated by ajax response
* - ajaxVar: string, the name of the request variable indicating the ID of the element triggering the AJAX request
* - ajaxType: string, the type (GET or POST) of the AJAX request
* - pagerClass: string, the CSS class for the pager container
* - tableClass: string, the CSS class for the table
* - selectableRows: integer, the number of rows that can be selected
* - updateSelector: string, the selector for choosing which elements can trigger ajax requests
* - beforeAjaxUpdate: function, the function to be called before ajax request is sent
* - afterAjaxUpdate: function, the function to be called after ajax response is received
* - ajaxUpdateError: function, the function to be called if an ajax error occurs
* - selectionChanged: function, the function to be called after the row selection is changed
* @return object the jQuery object
*/
init: function (options) {
var settings = $.extend({
ajaxUpdate: [],
ajaxVar: 'ajax',
ajaxType: 'GET',
pagerClass: 'pager',
loadingClass: 'loading',
filterClass: 'filters',
tableClass: 'items',
selectableRows: 1
// updateSelector: '#id .pager a, '#id .grid thead th a',
// beforeAjaxUpdate: function (id) {},
// afterAjaxUpdate: function (id, data) {},
// selectionChanged: function (id) {},
// url: 'ajax request URL'
}, options || {});
settings.tableClass = settings.tableClass.replace(/\s+/g, '.');
return this.each(function () {
var eventType,
$grid = $(this),
id = $grid.attr('id'),
pagerSelector = '#' + id + ' .' + settings.pagerClass.replace(/\s+/g, '.') + ' a',
sortSelector = '#' + id + ' .' + settings.tableClass + ' thead th a.sort-link',
inputSelector = '#' + id + ' .' + settings.filterClass + ' input, ' + '#' + id + ' .' + settings.filterClass + ' select';
settings.updateSelector = settings.updateSelector
.replace('{page}', pagerSelector)
.replace('{sort}', sortSelector);
settings.filterSelector = settings.filterSelector
.replace('{filter}', inputSelector);
gridSettings[id] = settings;
if (settings.ajaxUpdate.length > 0) {
$(document).on('click.yiiGridView', settings.updateSelector, function () {
// Check to see if History.js is enabled for our Browser
if (settings.enableHistory && window.History.enabled) {
// Ajaxify this link
var url = $(this).attr('href').split('?'),
params = $.deparam.querystring('?'+ (url[1] || ''));
delete params[settings.ajaxVar];
window.History.pushState(null, document.title, decodeURIComponent($.param.querystring(url[0], params)));
} else {
$('#' + id).yiiGridView('update', {url: $(this).attr('href')});
}
return false;
});
}
$(document).on('change.yiiGridView keydown.yiiGridView', settings.filterSelector, function (event) {
if (event.type === 'keydown') {
if (event.keyCode !== 13) {
return; // only react to enter key
} else {
eventType = 'keydown';
}
} else {
// prevent processing for both keydown and change events
if (eventType === 'keydown') {
eventType = '';
return;
}
}
var data = $(settings.filterSelector).serialize();
if (settings.pageVar !== undefined) {
data += '&' + settings.pageVar + '=1';
}
if (settings.enableHistory && settings.ajaxUpdate !== false && window.History.enabled) {
// Ajaxify this link
var url = $('#' + id).yiiGridView('getUrl'),
params = $.deparam.querystring($.param.querystring(url, data));
delete params[settings.ajaxVar];
window.History.pushState(null, document.title, decodeURIComponent($.param.querystring(url.substr(0, url.indexOf('?')), params)));
} else {
$('#' + id).yiiGridView('update', {data: data});
}
return false;
});
if (settings.enableHistory && settings.ajaxUpdate !== false && window.History.enabled) {
$(window).bind('statechange', function() { // Note: We are using statechange instead of popstate
var State = window.History.getState(); // Note: We are using History.getState() instead of event.state
$('#' + id).yiiGridView('update', {url: State.url});
});
}
if (settings.selectableRows > 0) {
selectCheckedRows(this.id);
$(document).on('click.yiiGridView', '#' + id + ' .' + settings.tableClass + ' > tbody > tr', function (e) {
var $currentGrid, $row, isRowSelected, $checks,
$target = $(e.target);
if ($target.closest('td').is('.empty,.button-column') || (e.target.type === 'checkbox' && !$target.hasClass('select-on-check'))) {
return;
}
$row = $(this);
$currentGrid = $('#' + id);
$checks = $('input.select-on-check', $currentGrid);
isRowSelected = $row.toggleClass('selected').hasClass('selected');
if (settings.selectableRows === 1) {
$row.siblings().removeClass('selected');
$checks.prop('checked', false);
}
$('input.select-on-check', $row).prop('checked', isRowSelected);
$("input.select-on-check-all", $currentGrid).prop('checked', $checks.length === $checks.filter(':checked').length);
if (settings.selectionChanged !== undefined) {
settings.selectionChanged(id);
}
});
if (settings.selectableRows > 1) {
$(document).on('click.yiiGridView', '#' + id + ' .select-on-check-all', function () {
var $currentGrid = $('#' + id),
$checks = $('input.select-on-check', $currentGrid),
$checksAll = $('input.select-on-check-all', $currentGrid),
$rows = $currentGrid.find('.' + settings.tableClass).children('tbody').children();
if (this.checked) {
$rows.addClass('selected');
$checks.prop('checked', true);
$checksAll.prop('checked', true);
} else {
$rows.removeClass('selected');
$checks.prop('checked', false);
$checksAll.prop('checked', false);
}
if (settings.selectionChanged !== undefined) {
settings.selectionChanged(id);
}
});
}
} else {
$(document).on('click.yiiGridView', '#' + id + ' .select-on-check', false);
}
});
},
/**
* Returns the key value for the specified row
* @param row integer the row number (zero-based index)
* @return string the key value
*/
getKey: function (row) {
return this.children('.keys').children('span').eq(row).text();
},
/**
* Returns the URL that generates the grid view content.
* @return string the URL that generates the grid view content.
*/
getUrl: function () {
var sUrl = gridSettings[this.attr('id')].url;
return sUrl || this.children('.keys').attr('title');
},
/**
* Returns the jQuery collection of the cells in the specified row.
* @param row integer the row number (zero-based index)
* @return jQuery the jQuery collection of the cells in the specified row.
*/
getRow: function (row) {
var sClass = gridSettings[this.attr('id')].tableClass;
return this.find('.' + sClass).children('tbody').children('tr').eq(row).children();
},
/**
* Returns the jQuery collection of the cells in the specified column.
* @param column integer the column number (zero-based index)
* @return jQuery the jQuery collection of the cells in the specified column.
*/
getColumn: function (column) {
var sClass = gridSettings[this.attr('id')].tableClass;
return this.find('.' + sClass).children('tbody').children('tr').children('td:nth-child(' + (column + 1) + ')');
},
/**
* Performs an AJAX-based update of the grid view contents.
* @param options map the AJAX request options (see jQuery.ajax API manual). By default,
* the URL to be requested is the one that generates the current content of the grid view.
* @return object the jQuery object
*/
update: function (options) {
var customError;
if (options && options.error !== undefined) {
customError = options.error;
delete options.error;
}
return this.each(function () {
var $form,
$grid = $(this),
id = $grid.attr('id'),
settings = gridSettings[id];
options = $.extend({
type: settings.ajaxType,
url: $grid.yiiGridView('getUrl'),
success: function (data) {
var $data = $('<div>' + data + '</div>');
$.each(settings.ajaxUpdate, function (i, el) {
var updateId = '#' + el;
$(updateId).replaceWith($(updateId, $data));
});
if (settings.afterAjaxUpdate !== undefined) {
settings.afterAjaxUpdate(id, data);
}
if (settings.selectableRows > 0) {
selectCheckedRows(id);
}
},
complete: function () {
yiiXHR[id] = null;
$grid.removeClass(settings.loadingClass);
},
error: function (XHR, textStatus, errorThrown) {
var ret, err;
if (XHR.readyState === 0 || XHR.status === 0) {
return;
}
if (customError !== undefined) {
ret = customError(XHR);
if (ret !== undefined && !ret) {
return;
}
}
switch (textStatus) {
case 'timeout':
err = 'The request timed out!';
break;
case 'parsererror':
err = 'Parser error!';
break;
case 'error':
if (XHR.status && !/^\s*$/.test(XHR.status)) {
err = 'Error ' + XHR.status;
} else {
err = 'Error';
}
if (XHR.responseText && !/^\s*$/.test(XHR.responseText)) {
err = err + ': ' + XHR.responseText;
}
break;
}
if (settings.ajaxUpdateError !== undefined) {
settings.ajaxUpdateError(XHR, textStatus, errorThrown, err);
} else if (err) {
alert(err);
}
}
}, options || {});
if (options.type === 'GET') {
if (options.data !== undefined) {
options.url = $.param.querystring(options.url, options.data);
options.data = {};
}
} else {
if (options.data === undefined) {
options.data = $(settings.filterSelector).serialize();
}
}
if(yiiXHR[id] != null){
yiiXHR[id].abort();
}
//class must be added after yiiXHR.abort otherwise ajax.error will remove it
$grid.addClass(settings.loadingClass);
if (settings.ajaxUpdate !== false) {
if(settings.ajaxVar) {
options.url = $.param.querystring(options.url, settings.ajaxVar + '=' + id);
}
if (settings.beforeAjaxUpdate !== undefined) {
settings.beforeAjaxUpdate(id, options);
}
yiiXHR[id] = $.ajax(options);
} else { // non-ajax mode
if (options.type === 'GET') {
window.location.href = options.url;
} else { // POST mode
$form = $('<form action="' + options.url + '" method="post"></form>').appendTo('body');
if (options.data === undefined) {
options.data = {};
}
if (options.data.returnUrl === undefined) {
options.data.returnUrl = window.location.href;
}
$.each(options.data, function (name, value) {
$form.append($('<input type="hidden" name="t" value="" />').attr('name', name).val(value));
});
$form.submit();
}
}
});
},
/**
* Returns the key values of the currently selected rows.
* @return array the key values of the currently selected rows.
*/
getSelection: function () {
var settings = gridSettings[this.attr('id')],
keys = this.find('.keys span'),
selection = [];
this.find('.' + settings.tableClass).children('tbody').children().each(function (i) {
if ($(this).hasClass('selected')) {
selection.push(keys.eq(i).text());
}
});
return selection;
},
/**
* Returns the key values of the currently checked rows.
* @param column_id string the ID of the column
* @return array the key values of the currently checked rows.
*/
getChecked: function (column_id) {
var settings = gridSettings[this.attr('id')],
keys = this.find('.keys span'),
checked = [];
if (column_id.substring(column_id.length - 2) !== '[]') {
column_id = column_id + '[]';
}
this.find('.' + settings.tableClass).children('tbody').children('tr').children('td').children('input[name="' + column_id + '"]').each(function (i) {
if (this.checked) {
checked.push(keys.eq(i).text());
}
});
return checked;
}
};
$.fn.yiiGridView = function (method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.yiiGridView');
return false;
}
};
/******************************************************************************
*** DEPRECATED METHODS
*** used before Yii 1.1.9
******************************************************************************/
$.fn.yiiGridView.settings = gridSettings;
/**
* Returns the key value for the specified row
* @param id string the ID of the grid view container
* @param row integer the row number (zero-based index)
* @return string the key value
*/
$.fn.yiiGridView.getKey = function (id, row) {
return $('#' + id).yiiGridView('getKey', row);
};
/**
* Returns the URL that generates the grid view content.
* @param id string the ID of the grid view container
* @return string the URL that generates the grid view content.
*/
$.fn.yiiGridView.getUrl = function (id) {
return $('#' + id).yiiGridView('getUrl');
};
/**
* Returns the jQuery collection of the cells in the specified row.
* @param id string the ID of the grid view container
* @param row integer the row number (zero-based index)
* @return jQuery the jQuery collection of the cells in the specified row.
*/
$.fn.yiiGridView.getRow = function (id, row) {
return $('#' + id).yiiGridView('getRow', row);
};
/**
* Returns the jQuery collection of the cells in the specified column.
* @param id string the ID of the grid view container
* @param column integer the column number (zero-based index)
* @return jQuery the jQuery collection of the cells in the specified column.
*/
$.fn.yiiGridView.getColumn = function (id, column) {
return $('#' + id).yiiGridView('getColumn', column);
};
/**
* Performs an AJAX-based update of the grid view contents.
* @param id string the ID of the grid view container
* @param options map the AJAX request options (see jQuery.ajax API manual). By default,
* the URL to be requested is the one that generates the current content of the grid view.
*/
$.fn.yiiGridView.update = function (id, options) {
$('#' + id).yiiGridView('update', options);
};
/**
* Returns the key values of the currently selected rows.
* @param id string the ID of the grid view container
* @return array the key values of the currently selected rows.
*/
$.fn.yiiGridView.getSelection = function (id) {
return $('#' + id).yiiGridView('getSelection');
};
/**
* Returns the key values of the currently checked rows.
* @param id string the ID of the grid view container
* @param column_id string the ID of the column
* @return array the key values of the currently checked rows.
*/
$.fn.yiiGridView.getChecked = function (id, column_id) {
return $('#' + id).yiiGridView('getChecked', column_id);
};
})(jQuery);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,125 @@
.grid-view-loading
{
background:url(loading.gif) no-repeat;
}
.grid-view
{
padding: 15px 0;
}
.grid-view table.items
{
background: white;
border-collapse: collapse;
width: 100%;
border: 1px #D0E3EF solid;
}
.grid-view table.items th, .grid-view table.items td
{
font-size: 0.9em;
border: 1px white solid;
padding: 0.3em;
}
.grid-view table.items th
{
color: white;
background: url("bg.gif") repeat-x scroll left top white;
text-align: center;
}
.grid-view table.items th a
{
color: #EEE;
font-weight: bold;
text-decoration: none;
}
.grid-view table.items th a:hover
{
color: #FFF;
}
.grid-view table.items th a.asc
{
background:url(up.gif) right center no-repeat;
padding-right: 10px;
}
.grid-view table.items th a.desc
{
background:url(down.gif) right center no-repeat;
padding-right: 10px;
}
.grid-view table.items tr.even
{
background: #F8F8F8;
}
.grid-view table.items tr.odd
{
background: #E5F1F4;
}
.grid-view table.items tr.selected
{
background: #BCE774;
}
.grid-view table.items tr:hover.selected
{
background: #CCFF66;
}
.grid-view table.items tbody tr:hover
{
background: #ECFBD4;
}
.grid-view .link-column img
{
border: 0;
}
.grid-view .button-column
{
text-align: center;
width: 60px;
}
.grid-view .button-column img
{
border: 0;
}
.grid-view .checkbox-column
{
width: 15px;
}
.grid-view .summary
{
margin: 0 0 5px 0;
text-align: right;
}
.grid-view .pager
{
margin: 5px 0 0 0;
text-align: right;
}
.grid-view .empty
{
font-style: italic;
}
.grid-view .filters input,
.grid-view .filters select
{
width: 100%;
border: 1px solid #ccc;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 B

View File

@@ -0,0 +1,181 @@
/**
* jQuery Yii ListView plugin file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2010 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
;(function($) {
var yiiXHR = {};
/**
* yiiListView set function.
* @param options map settings for the list view. Availablel options are as follows:
* - ajaxUpdate: array, IDs of the containers whose content may be updated by ajax response
* - ajaxVar: string, the name of the request variable indicating the ID of the element triggering the AJAX request
* - ajaxType: string, the type (GET or POST) of the AJAX request
* - pagerClass: string, the CSS class for the pager container
* - sorterClass: string, the CSS class for the sorter container
* - updateSelector: string, the selector for choosing which elements can trigger ajax requests
* - beforeAjaxUpdate: function, the function to be called before ajax request is sent
* - afterAjaxUpdate: function, the function to be called after ajax response is received
*/
$.fn.yiiListView = function(options) {
return this.each(function(){
var settings = $.extend({}, $.fn.yiiListView.defaults, options || {}),
$this = $(this),
id = $this.attr('id');
if(settings.updateSelector == undefined) {
settings.updateSelector = '#'+id+' .'+settings.pagerClass.replace(/\s+/g,'.')+' a, #'+id+' .'+settings.sorterClass.replace(/\s+/g,'.')+' a';
}
$.fn.yiiListView.settings[id] = settings;
if(settings.ajaxUpdate.length > 0) {
$(document).on('click.yiiListView', settings.updateSelector,function(){
if(settings.enableHistory && window.History.enabled) {
var url = $(this).attr('href').split('?'),
params = $.deparam.querystring('?'+ (url[1] || ''));
delete params[settings.ajaxVar];
window.History.pushState(null, document.title, decodeURIComponent($.param.querystring(url[0], params)));
} else {
$.fn.yiiListView.update(id, {url: $(this).attr('href')});
}
return false;
});
if(settings.enableHistory && window.History.enabled) {
$(window).bind('statechange', function() { // Note: We are using statechange instead of popstate
var State = window.History.getState(); // Note: We are using History.getState() instead of event.state
$.fn.yiiListView.update(id, {url: State.url});
});
}
}
});
};
$.fn.yiiListView.defaults = {
ajaxUpdate: [],
ajaxVar: 'ajax',
ajaxType: 'GET',
pagerClass: 'pager',
loadingClass: 'loading',
sorterClass: 'sorter'
// updateSelector: '#id .pager a, '#id .sort a',
// beforeAjaxUpdate: function(id) {},
// afterAjaxUpdate: function(id, data) {},
// url: 'ajax request URL'
};
$.fn.yiiListView.settings = {};
/**
* Returns the key value for the specified row
* @param id string the ID of the list view container
* @param index integer the zero-based index of the data item
* @return string the key value
*/
$.fn.yiiListView.getKey = function(id, index) {
return $('#'+id+' > div.keys > span:eq('+index+')').text();
};
/**
* Returns the URL that generates the list view content.
* @param id string the ID of the list view container
* @return string the URL that generates the list view content.
*/
$.fn.yiiListView.getUrl = function(id) {
var settings = $.fn.yiiListView.settings[id];
return settings.url || $('#'+id+' > div.keys').attr('title');
};
/**
* Performs an AJAX-based update of the list view contents.
* @param id string the ID of the list view container
* @param options map the AJAX request options (see jQuery.ajax API manual). By default,
* the URL to be requested is the one that generates the current content of the list view.
*/
$.fn.yiiListView.update = function(id, options) {
var customError,
settings = $.fn.yiiListView.settings[id];
if (options && options.error !== undefined) {
customError = options.error;
delete options.error;
}
options = $.extend({
type: settings.ajaxType,
url: $.fn.yiiListView.getUrl(id),
success: function(data,status) {
$.each(settings.ajaxUpdate, function(i,v) {
var id='#'+v;
$(id).replaceWith($(id,'<div>'+data+'</div>'));
});
if(settings.afterAjaxUpdate != undefined)
settings.afterAjaxUpdate(id, data);
},
complete: function() {
$('#'+id).removeClass(settings.loadingClass);
yiiXHR[id] = null;
},
error: function(XHR, textStatus, errorThrown) {
var ret, err;
if (XHR.readyState === 0 || XHR.status === 0) {
return;
}
if (customError !== undefined) {
ret = customError(XHR);
if (ret !== undefined && !ret) {
return;
}
}
switch (textStatus) {
case 'timeout':
err = 'The request timed out!';
break;
case 'parsererror':
err = 'Parser error!';
break;
case 'error':
if (XHR.status && !/^\s*$/.test(XHR.status)) {
err = 'Error ' + XHR.status;
} else {
err = 'Error';
}
if (XHR.responseText && !/^\s*$/.test(XHR.responseText)) {
err = err + ': ' + XHR.responseText;
}
break;
}
if (settings.ajaxUpdateError !== undefined) {
settings.ajaxUpdateError(XHR, textStatus, errorThrown, err);
} else if (err) {
alert(err);
}
}
}, options || {});
if(options.data!=undefined && options.type=='GET') {
options.url = $.param.querystring(options.url, options.data);
options.data = {};
}
if(settings.ajaxVar)
options.url = $.param.querystring(options.url, settings.ajaxVar+'='+id);
if(yiiXHR[id] != null) {
yiiXHR[id].abort();
}
$('#'+id).addClass(settings.loadingClass);
if(settings.beforeAjaxUpdate != undefined)
settings.beforeAjaxUpdate(id);
yiiXHR[id] = $.ajax(options);
};
})(jQuery);

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,56 @@
.list-view-loading
{
background:url(loading.gif) no-repeat;
}
.list-view .summary
{
margin: 0 0 5px 0;
text-align: right;
}
.list-view .sorter
{
margin: 0 0 5px 0;
text-align: right;
}
.list-view .pager
{
margin: 5px 0 0 0;
text-align: right;
}
.list-view .sorter
{
font-size: 0.9em;
}
.list-view .sorter ul
{
display: inline;
list-style-image:none;
list-style-position:outside;
list-style-type:none;
margin:0;
padding:0;
}
.list-view .sorter li
{
display: inline;
margin: 0 0 0 5px;
padding: 0;
}
.list-view .sorter a.asc
{
background:url(up.gif) right center no-repeat;
padding-right: 10px;
}
.list-view .sorter a.desc
{
background:url(down.gif) right center no-repeat;
padding-right: 10px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 B

View File

@@ -0,0 +1,349 @@
<?php
/**
* CButtonColumn class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.grid.CGridColumn');
/**
* CButtonColumn represents a grid view column that renders one or several buttons.
*
* By default, it will display three buttons, "view", "update" and "delete", which triggers the corresponding
* actions on the model of the row.
*
* By configuring {@link buttons} and {@link template} properties, the column can display other buttons
* and customize the display order of the buttons.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets.grid
* @since 1.1
*/
class CButtonColumn extends CGridColumn
{
/**
* @var array the HTML options for the data cell tags.
*/
public $htmlOptions=array('class'=>'button-column');
/**
* @var array the HTML options for the header cell tag.
*/
public $headerHtmlOptions=array('class'=>'button-column');
/**
* @var array the HTML options for the footer cell tag.
*/
public $footerHtmlOptions=array('class'=>'button-column');
/**
* @var string the template that is used to render the content in each data cell.
* These default tokens are recognized: {view}, {update} and {delete}. If the {@link buttons} property
* defines additional buttons, their IDs are also recognized here. For example, if a button named 'preview'
* is declared in {@link buttons}, we can use the token '{preview}' here to specify where to display the button.
*/
public $template='{view} {update} {delete}';
/**
* @var string the label for the view button. Defaults to "View".
* Note that the label will not be HTML-encoded when rendering.
*/
public $viewButtonLabel;
/**
* @var string the image URL for the view button. If not set, an integrated image will be used.
* You may set this property to be false to render a text link instead.
*/
public $viewButtonImageUrl;
/**
* @var string a PHP expression that is evaluated for every view button and whose result is used
* as the URL for the view button. In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based)</li>
* <li><code>$data</code> the data model for the row</li>
* <li><code>$this</code> the column object</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*/
public $viewButtonUrl='Yii::app()->controller->createUrl("view",array("id"=>$data->primaryKey))';
/**
* @var array the HTML options for the view button tag.
*/
public $viewButtonOptions=array('class'=>'view');
/**
* @var string the label for the update button. Defaults to "Update".
* Note that the label will not be HTML-encoded when rendering.
*/
public $updateButtonLabel;
/**
* @var string the image URL for the update button. If not set, an integrated image will be used.
* You may set this property to be false to render a text link instead.
*/
public $updateButtonImageUrl;
/**
* @var string a PHP expression that is evaluated for every update button and whose result is used
* as the URL for the update button. In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based)</li>
* <li><code>$data</code> the data model for the row</li>
* <li><code>$this</code> the column object</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*/
public $updateButtonUrl='Yii::app()->controller->createUrl("update",array("id"=>$data->primaryKey))';
/**
* @var array the HTML options for the update button tag.
*/
public $updateButtonOptions=array('class'=>'update');
/**
* @var string the label for the delete button. Defaults to "Delete".
* Note that the label will not be HTML-encoded when rendering.
*/
public $deleteButtonLabel;
/**
* @var string the image URL for the delete button. If not set, an integrated image will be used.
* You may set this property to be false to render a text link instead.
*/
public $deleteButtonImageUrl;
/**
* @var string a PHP expression that is evaluated for every delete button and whose result is used
* as the URL for the delete button. In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based)</li>
* <li><code>$data</code> the data model for the row</li>
* <li><code>$this</code> the column object</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*/
public $deleteButtonUrl='Yii::app()->controller->createUrl("delete",array("id"=>$data->primaryKey))';
/**
* @var array the HTML options for the delete button tag.
*/
public $deleteButtonOptions=array('class'=>'delete');
/**
* @var string the confirmation message to be displayed when delete button is clicked.
* By setting this property to be false, no confirmation message will be displayed.
* This property is used only if <code>$this->buttons['delete']['click']</code> is not set.
*/
public $deleteConfirmation;
/**
* @var string a javascript function that will be invoked after the delete ajax call.
* This property is used only if <code>$this->buttons['delete']['click']</code> is not set.
*
* The function signature is <code>function(link, success, data)</code>
* <ul>
* <li><code>link</code> references the delete link.</li>
* <li><code>success</code> status of the ajax call, true if the ajax call was successful, false if the ajax call failed.
* <li><code>data</code> the data returned by the server in case of a successful call or XHR object in case of error.
* </ul>
* Note that if success is true it does not mean that the delete was successful, it only means that the ajax call was successful.
*
* Example:
* <pre>
* array(
* class'=>'CButtonColumn',
* 'afterDelete'=>'function(link,success,data){ if(success) alert("Delete completed successfuly"); }',
* ),
* </pre>
*/
public $afterDelete;
/**
* @var array the configuration for buttons. Each array element specifies a single button
* which has the following format:
* <pre>
* 'buttonID' => array(
* 'label'=>'...', // text label of the button
* 'url'=>'...', // a PHP expression for generating the URL of the button
* 'imageUrl'=>'...', // image URL of the button. If not set or false, a text link is used
* 'options'=>array(...), // HTML options for the button tag
* 'click'=>'...', // a JS function to be invoked when the button is clicked
* 'visible'=>'...', // a PHP expression for determining whether the button is visible
* )
* </pre>
*
* In the PHP expression for the 'url' option and/or 'visible' option, the variable <code>$row</code>
* refers to the current row number (zero-based), and <code>$data</code> refers to the data model for
* the row.
* The PHP expression will be evaluated using {@link evaluateExpression}.
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*
* If the 'buttonID' is 'view', 'update' or 'delete' the options will be applied to the default buttons.
*
* Note that in order to display non-default buttons, the {@link template} property needs to
* be configured so that the corresponding button IDs appear as tokens in the template.
*/
public $buttons=array();
/**
* Initializes the column.
* This method registers necessary client script for the button column.
*/
public function init()
{
$this->initDefaultButtons();
foreach($this->buttons as $id=>$button)
{
if(strpos($this->template,'{'.$id.'}')===false)
unset($this->buttons[$id]);
elseif(isset($button['click']))
{
if(!isset($button['options']['class']))
$this->buttons[$id]['options']['class']=$id;
if(!($button['click'] instanceof CJavaScriptExpression))
$this->buttons[$id]['click']=new CJavaScriptExpression($button['click']);
}
}
$this->registerClientScript();
}
/**
* Initializes the default buttons (view, update and delete).
*/
protected function initDefaultButtons()
{
if($this->viewButtonLabel===null)
$this->viewButtonLabel=Yii::t('zii','View');
if($this->updateButtonLabel===null)
$this->updateButtonLabel=Yii::t('zii','Update');
if($this->deleteButtonLabel===null)
$this->deleteButtonLabel=Yii::t('zii','Delete');
if($this->viewButtonImageUrl===null)
$this->viewButtonImageUrl=$this->grid->baseScriptUrl.'/view.png';
if($this->updateButtonImageUrl===null)
$this->updateButtonImageUrl=$this->grid->baseScriptUrl.'/update.png';
if($this->deleteButtonImageUrl===null)
$this->deleteButtonImageUrl=$this->grid->baseScriptUrl.'/delete.png';
if($this->deleteConfirmation===null)
$this->deleteConfirmation=Yii::t('zii','Are you sure you want to delete this item?');
foreach(array('view','update','delete') as $id)
{
$button=array(
'label'=>$this->{$id.'ButtonLabel'},
'url'=>$this->{$id.'ButtonUrl'},
'imageUrl'=>$this->{$id.'ButtonImageUrl'},
'options'=>$this->{$id.'ButtonOptions'},
);
if(isset($this->buttons[$id]))
$this->buttons[$id]=array_merge($button,$this->buttons[$id]);
else
$this->buttons[$id]=$button;
}
if(!isset($this->buttons['delete']['click']))
{
if(is_string($this->deleteConfirmation))
$confirmation="if(!confirm(".CJavaScript::encode($this->deleteConfirmation).")) return false;";
else
$confirmation='';
if(Yii::app()->request->enableCsrfValidation)
{
$csrfTokenName = Yii::app()->request->csrfTokenName;
$csrfToken = Yii::app()->request->csrfToken;
$csrf = "\n\t\tdata:{ '$csrfTokenName':'$csrfToken' },";
}
else
$csrf = '';
if($this->afterDelete===null)
$this->afterDelete='function(){}';
$this->buttons['delete']['click']=<<<EOD
function() {
$confirmation
var th = this,
afterDelete = $this->afterDelete;
jQuery('#{$this->grid->id}').yiiGridView('update', {
type: 'POST',
url: jQuery(this).attr('href'),$csrf
success: function(data) {
jQuery('#{$this->grid->id}').yiiGridView('update');
afterDelete(th, true, data);
},
error: function(XHR) {
return afterDelete(th, false, XHR);
}
});
return false;
}
EOD;
}
}
/**
* Registers the client scripts for the button column.
*/
protected function registerClientScript()
{
$js=array();
foreach($this->buttons as $id=>$button)
{
if(isset($button['click']))
{
$function=CJavaScript::encode($button['click']);
$class=preg_replace('/\s+/','.',$button['options']['class']);
$js[]="jQuery(document).on('click','#{$this->grid->id} a.{$class}',$function);";
}
}
if($js!==array())
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$this->id, implode("\n",$js));
}
/**
* Renders the data cell content.
* This method renders the view, update and delete buttons in the data cell.
* @param integer $row the row number (zero-based)
* @param mixed $data the data associated with the row
*/
protected function renderDataCellContent($row,$data)
{
$tr=array();
ob_start();
foreach($this->buttons as $id=>$button)
{
$this->renderButton($id,$button,$row,$data);
$tr['{'.$id.'}']=ob_get_contents();
ob_clean();
}
ob_end_clean();
echo strtr($this->template,$tr);
}
/**
* Renders a link button.
* @param string $id the ID of the button
* @param array $button the button configuration which may contain 'label', 'url', 'imageUrl' and 'options' elements.
* See {@link buttons} for more details.
* @param integer $row the row number (zero-based)
* @param mixed $data the data object associated with the row
*/
protected function renderButton($id,$button,$row,$data)
{
if (isset($button['visible']) && !$this->evaluateExpression($button['visible'],array('row'=>$row,'data'=>$data)))
return;
$label=isset($button['label']) ? $button['label'] : $id;
$url=isset($button['url']) ? $this->evaluateExpression($button['url'],array('data'=>$data,'row'=>$row)) : '#';
$options=isset($button['options']) ? $button['options'] : array();
if(!isset($options['title']))
$options['title']=$label;
if(isset($button['imageUrl']) && is_string($button['imageUrl']))
echo CHtml::link(CHtml::image($button['imageUrl'],$label),$url,$options);
else
echo CHtml::link($label,$url,$options);
}
}

View File

@@ -0,0 +1,248 @@
<?php
/**
* CCheckBoxColumn class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.grid.CGridColumn');
/**
* CCheckBoxColumn represents a grid view column of checkboxes.
*
* CCheckBoxColumn supports no checking (read-only), single check and multiple checking.
* The mode is determined according to {@link selectableRows}. When in multiple checking mode, the header cell will display
* an additional checkbox, clicking on which will check or uncheck all of the checkboxes in the data cells.
* The header cell can be customized by {@link headerTemplate}.
*
* Additionally selecting a checkbox can select a grid view row (depending on {@link CGridView::selectableRows} value) if
* {@link selectableRows} is null (default).
*
* By default, the checkboxes rendered in data cells will have the values that are the same as
* the key values of the data model. One may change this by setting either {@link name} or
* {@link value}.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets.grid
* @since 1.1
*/
class CCheckBoxColumn extends CGridColumn
{
/**
* @var string the attribute name of the data model. The corresponding attribute value will be rendered
* in each data cell as the checkbox value. Note that if {@link value} is specified, this property will be ignored.
* @see value
*/
public $name;
/**
* @var string a PHP expression that will be evaluated for every data cell and whose result will be rendered
* in each data cell as the checkbox value. In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based)</li>
* <li><code>$data</code> the data model for the row</li>
* <li><code>$this</code> the column object</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*/
public $value;
/**
* @var string a PHP expression that will be evaluated for every data cell and whose result will
* determine if checkbox for each data cell is checked. In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based)</li>
* <li><code>$data</code> the data model for the row</li>
* <li><code>$this</code> the column object</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
* @since 1.1.4
*/
public $checked;
/**
* @var string a PHP expression that will be evaluated for every data cell and whose result will
* determine if checkbox for each data cell is disabled. In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based)</li>
* <li><code>$data</code> the data model for the row</li>
* <li><code>$this</code> the column object</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*
* Note that expression result will overwrite value set with <code>checkBoxHtmlOptions['disabled']</code>.
* @since 1.1.13
*/
public $disabled;
/**
* @var array the HTML options for the data cell tags.
*/
public $htmlOptions=array('class'=>'checkbox-column');
/**
* @var array the HTML options for the header cell tag.
*/
public $headerHtmlOptions=array('class'=>'checkbox-column');
/**
* @var array the HTML options for the footer cell tag.
*/
public $footerHtmlOptions=array('class'=>'checkbox-column');
/**
* @var array the HTML options for the checkboxes.
*/
public $checkBoxHtmlOptions=array();
/**
* @var integer the number of rows that can be checked.
* Possible values:
* <ul>
* <li>0 - the state of the checkbox cannot be changed (read-only mode)</li>
* <li>1 - only one row can be checked. Checking a checkbox has nothing to do with selecting the row</li>
* <li>2 or more - multiple checkboxes can be checked. Checking a checkbox has nothing to do with selecting the row</li>
* <li>null - {@link CGridView::selectableRows} is used to control how many checkboxes can be checked.
* Checking a checkbox will also select the row.</li>
* </ul>
* You may also call the JavaScript function <code>$(gridID).yiiGridView('getChecked', columnID)</code>
* to retrieve the key values of the checked rows.
* @since 1.1.6
*/
public $selectableRows=null;
/**
* @var string the template to be used to control the layout of the header cell.
* The token "{item}" is recognized and it will be replaced with a "check all" checkbox.
* By default if in multiple checking mode, the header cell will display an additional checkbox,
* clicking on which will check or uncheck all of the checkboxes in the data cells.
* See {@link selectableRows} for more details.
* @since 1.1.11
*/
public $headerTemplate='{item}';
/**
* Initializes the column.
* This method registers necessary client script for the checkbox column.
*/
public function init()
{
if(isset($this->checkBoxHtmlOptions['name']))
$name=$this->checkBoxHtmlOptions['name'];
else
{
$name=$this->id;
if(substr($name,-2)!=='[]')
$name.='[]';
$this->checkBoxHtmlOptions['name']=$name;
}
$name=strtr($name,array('['=>"\\[",']'=>"\\]"));
if($this->selectableRows===null)
{
if(isset($this->checkBoxHtmlOptions['class']))
$this->checkBoxHtmlOptions['class'].=' select-on-check';
else
$this->checkBoxHtmlOptions['class']='select-on-check';
return;
}
$cball=$cbcode='';
if($this->selectableRows==0)
{
//.. read only
$cbcode="return false;";
}
elseif($this->selectableRows==1)
{
//.. only one can be checked, uncheck all other
$cbcode="jQuery(\"input:not(#\"+this.id+\")[name='$name']\").prop('checked',false);";
}
elseif(strpos($this->headerTemplate,'{item}')!==false)
{
//.. process check/uncheck all
$cball=<<<CBALL
jQuery(document).on('click','#{$this->id}_all',function() {
var checked=this.checked;
jQuery("input[name='$name']:enabled").each(function() {this.checked=checked;});
});
CBALL;
$cbcode="jQuery('#{$this->id}_all').prop('checked', jQuery(\"input[name='$name']\").length==jQuery(\"input[name='$name']:checked\").length);";
}
if($cbcode!=='')
{
$js=$cball;
$js.=<<<EOD
jQuery(document).on('click', "input[name='$name']", function() {
$cbcode
});
EOD;
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$this->id,$js);
}
}
/**
* Renders the header cell content.
* This method will render a checkbox in the header when {@link selectableRows} is greater than 1
* or in case {@link selectableRows} is null when {@link CGridView::selectableRows} is greater than 1.
*/
protected function renderHeaderCellContent()
{
if(trim($this->headerTemplate)==='')
{
echo $this->grid->blankDisplay;
return;
}
$item = '';
if($this->selectableRows===null && $this->grid->selectableRows>1)
$item = CHtml::checkBox($this->id.'_all',false,array('class'=>'select-on-check-all'));
elseif($this->selectableRows>1)
$item = CHtml::checkBox($this->id.'_all',false);
else
{
ob_start();
parent::renderHeaderCellContent();
$item = ob_get_clean();
}
echo strtr($this->headerTemplate,array(
'{item}'=>$item,
));
}
/**
* Renders the data cell content.
* This method renders a checkbox in the data cell.
* @param integer $row the row number (zero-based)
* @param mixed $data the data associated with the row
*/
protected function renderDataCellContent($row,$data)
{
if($this->value!==null)
$value=$this->evaluateExpression($this->value,array('data'=>$data,'row'=>$row));
elseif($this->name!==null)
$value=CHtml::value($data,$this->name);
else
$value=$this->grid->dataProvider->keys[$row];
$checked = false;
if($this->checked!==null)
$checked=$this->evaluateExpression($this->checked,array('data'=>$data,'row'=>$row));
$options=$this->checkBoxHtmlOptions;
if($this->disabled!==null)
$options['disabled']=$this->evaluateExpression($this->disabled,array('data'=>$data,'row'=>$row));
$name=$options['name'];
unset($options['name']);
$options['value']=$value;
$options['id']=$this->id.'_'.$row;
echo CHtml::checkBox($name,$checked,$options);
}
}

View File

@@ -0,0 +1,142 @@
<?php
/**
* CDataColumn class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.grid.CGridColumn');
/**
* CDataColumn represents a grid view column that is associated with a data attribute or PHP expression.
*
* Either {@link name} or {@link value} should be specified. The former specifies
* a data attribute name, while the latter a PHP expression whose value should be rendered instead.
*
* The property {@link sortable} determines whether the grid view can be sorted according to this column.
* Note that the {@link name} should always be set if the column needs to be sortable. The {@link name}
* value will be used by {@link CSort} to render a clickable link in the header cell to trigger the sorting.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets.grid
* @since 1.1
*/
class CDataColumn extends CGridColumn
{
/**
* @var string the attribute name of the data model. Used for column sorting, filtering and to render the corresponding
* attribute value in each data cell. If {@link value} is specified it will be used to rendered the data cell instead of the attribute value.
* @see value
* @see sortable
*/
public $name;
/**
* @var string a PHP expression that will be evaluated for every data cell using {@link evaluateExpression} and whose result will be rendered
* as the content of the data cell.
* In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based).</li>
* <li><code>$data</code> the data model for the row.</li>
* <li><code>$this</code> the column object.</li>
* </ul>
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*/
public $value;
/**
* @var string the type of the attribute value. This determines how the attribute value is formatted for display.
* Valid values include those recognizable by {@link CGridView::formatter}, such as: raw, text, ntext, html, date, time,
* datetime, boolean, number, email, image, url. For more details, please refer to {@link CFormatter}.
* Defaults to 'text' which means the attribute value will be HTML-encoded.
*/
public $type='text';
/**
* @var boolean whether the column is sortable. If so, the header cell will contain a link that may trigger the sorting.
* Defaults to true. Note that if {@link name} is not set, or if {@link name} is not allowed by {@link CSort},
* this property will be treated as false.
* @see name
*/
public $sortable=true;
/**
* @var mixed the HTML code representing a filter input (eg a text field, a dropdown list)
* that is used for this data column. This property is effective only when
* {@link CGridView::filter} is set.
* If this property is not set, a text field will be generated as the filter input;
* If this property is an array, a dropdown list will be generated that uses this property value as
* the list options.
* If you don't want a filter for this data column, set this value to false.
* @since 1.1.1
*/
public $filter;
/**
* Initializes the column.
*/
public function init()
{
parent::init();
if($this->name===null)
$this->sortable=false;
if($this->name===null && $this->value===null)
throw new CException(Yii::t('zii','Either "name" or "value" must be specified for CDataColumn.'));
}
/**
* Renders the filter cell content.
* This method will render the {@link filter} as is if it is a string.
* If {@link filter} is an array, it is assumed to be a list of options, and a dropdown selector will be rendered.
* Otherwise if {@link filter} is not false, a text field is rendered.
* @since 1.1.1
*/
protected function renderFilterCellContent()
{
if(is_string($this->filter))
echo $this->filter;
elseif($this->filter!==false && $this->grid->filter!==null && $this->name!==null && strpos($this->name,'.')===false)
{
if(is_array($this->filter))
echo CHtml::activeDropDownList($this->grid->filter, $this->name, $this->filter, array('id'=>false,'prompt'=>''));
elseif($this->filter===null)
echo CHtml::activeTextField($this->grid->filter, $this->name, array('id'=>false));
}
else
parent::renderFilterCellContent();
}
/**
* Renders the header cell content.
* This method will render a link that can trigger the sorting if the column is sortable.
*/
protected function renderHeaderCellContent()
{
if($this->grid->enableSorting && $this->sortable && $this->name!==null)
echo $this->grid->dataProvider->getSort()->link($this->name,$this->header,array('class'=>'sort-link'));
elseif($this->name!==null && $this->header===null)
{
if($this->grid->dataProvider instanceof CActiveDataProvider)
echo CHtml::encode($this->grid->dataProvider->model->getAttributeLabel($this->name));
else
echo CHtml::encode($this->name);
}
else
parent::renderHeaderCellContent();
}
/**
* Renders the data cell content.
* This method evaluates {@link value} or {@link name} and renders the result.
* @param integer $row the row number (zero-based)
* @param mixed $data the data associated with the row
*/
protected function renderDataCellContent($row,$data)
{
if($this->value!==null)
$value=$this->evaluateExpression($this->value,array('data'=>$data,'row'=>$row));
elseif($this->name!==null)
$value=CHtml::value($data,$this->name);
echo $value===null ? $this->grid->nullDisplay : $this->grid->getFormatter()->format($value,$this->type);
}
}

View File

@@ -0,0 +1,206 @@
<?php
/**
* CGridColumn class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CGridColumn is the base class for all grid view column classes.
*
* A CGridColumn object represents the specification for rendering the cells in
* a particular grid view column.
*
* In a column, there is one header cell, multiple data cells, and an optional footer cell.
* Child classes may override {@link renderHeaderCellContent}, {@link renderDataCellContent}
* and {@link renderFooterCellContent} to customize how these cells are rendered.
*
* @property boolean $hasFooter Whether this column has a footer cell.
* This is determined based on whether {@link footer} is set.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets.grid
* @since 1.1
*/
abstract class CGridColumn extends CComponent
{
/**
* @var string the ID of this column. This value should be unique among all grid view columns.
* If this is not set, it will be assigned one automatically.
*/
public $id;
/**
* @var CGridView the grid view object that owns this column.
*/
public $grid;
/**
* @var string the header cell text. Note that it will not be HTML-encoded.
*/
public $header;
/**
* @var string the footer cell text. Note that it will not be HTML-encoded.
*/
public $footer;
/**
* @var boolean whether this column is visible. Defaults to true.
*/
public $visible=true;
/**
* @var string a PHP expression that is evaluated for every data cell and whose result
* is used as the CSS class name for the data cell. In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based)</li>
* <li><code>$data</code> the data model for the row</li>
* <li><code>$this</code> the column object</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*/
public $cssClassExpression;
/**
* @var array the HTML options for the data cell tags.
*/
public $htmlOptions=array();
/**
* @var array the HTML options for the filter cell tag.
*/
public $filterHtmlOptions=array();
/**
* @var array the HTML options for the header cell tag.
*/
public $headerHtmlOptions=array();
/**
* @var array the HTML options for the footer cell tag.
*/
public $footerHtmlOptions=array();
/**
* Constructor.
* @param CGridView $grid the grid view that owns this column.
*/
public function __construct($grid)
{
$this->grid=$grid;
}
/**
* Initializes the column.
* This method is invoked by the grid view when it initializes itself before rendering.
* You may override this method to prepare the column for rendering.
*/
public function init()
{
}
/**
* @return boolean whether this column has a footer cell.
* This is determined based on whether {@link footer} is set.
*/
public function getHasFooter()
{
return $this->footer!==null;
}
/**
* Renders the filter cell.
* @since 1.1.1
*/
public function renderFilterCell()
{
echo CHtml::openTag('td',$this->filterHtmlOptions);
$this->renderFilterCellContent();
echo "</td>";
}
/**
* Renders the header cell.
*/
public function renderHeaderCell()
{
$this->headerHtmlOptions['id']=$this->id;
echo CHtml::openTag('th',$this->headerHtmlOptions);
$this->renderHeaderCellContent();
echo "</th>";
}
/**
* Renders a data cell.
* @param integer $row the row number (zero-based)
*/
public function renderDataCell($row)
{
$data=$this->grid->dataProvider->data[$row];
$options=$this->htmlOptions;
if($this->cssClassExpression!==null)
{
$class=$this->evaluateExpression($this->cssClassExpression,array('row'=>$row,'data'=>$data));
if(!empty($class))
{
if(isset($options['class']))
$options['class'].=' '.$class;
else
$options['class']=$class;
}
}
echo CHtml::openTag('td',$options);
$this->renderDataCellContent($row,$data);
echo '</td>';
}
/**
* Renders the footer cell.
*/
public function renderFooterCell()
{
echo CHtml::openTag('td',$this->footerHtmlOptions);
$this->renderFooterCellContent();
echo '</td>';
}
/**
* Renders the header cell content.
* The default implementation simply renders {@link header}.
* This method may be overridden to customize the rendering of the header cell.
*/
protected function renderHeaderCellContent()
{
echo trim($this->header)!=='' ? $this->header : $this->grid->blankDisplay;
}
/**
* Renders the footer cell content.
* The default implementation simply renders {@link footer}.
* This method may be overridden to customize the rendering of the footer cell.
*/
protected function renderFooterCellContent()
{
echo trim($this->footer)!=='' ? $this->footer : $this->grid->blankDisplay;
}
/**
* Renders the data cell content.
* This method SHOULD be overridden to customize the rendering of the data cell.
* @param integer $row the row number (zero-based)
* @param mixed $data the data associated with the row
*/
protected function renderDataCellContent($row,$data)
{
echo $this->grid->blankDisplay;
}
/**
* Renders the filter cell content.
* The default implementation simply renders a space.
* This method may be overridden to customize the rendering of the filter cell (if any).
* @since 1.1.1
*/
protected function renderFilterCellContent()
{
echo $this->grid->blankDisplay;
}
}

View File

@@ -0,0 +1,649 @@
<?php
/**
* CGridView class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.CBaseListView');
Yii::import('zii.widgets.grid.CDataColumn');
Yii::import('zii.widgets.grid.CLinkColumn');
Yii::import('zii.widgets.grid.CButtonColumn');
Yii::import('zii.widgets.grid.CCheckBoxColumn');
/**
* CGridView displays a list of data items in terms of a table.
*
* Each row of the table represents the data of a single data item, and a column usually represents
* an attribute of the item (some columns may correspond to complex expression of attributes or static text).
*
* CGridView supports both sorting and pagination of the data items. The sorting
* and pagination can be done in AJAX mode or normal page request. A benefit of using CGridView is that
* when the user browser disables JavaScript, the sorting and pagination automatically degenerate
* to normal page requests and are still functioning as expected.
*
* CGridView should be used together with a {@link IDataProvider data provider}, preferrably a
* {@link CActiveDataProvider}.
*
* The minimal code needed to use CGridView is as follows:
*
* <pre>
* $dataProvider=new CActiveDataProvider('Post');
*
* $this->widget('zii.widgets.grid.CGridView', array(
* 'dataProvider'=>$dataProvider,
* ));
* </pre>
*
* The above code first creates a data provider for the <code>Post</code> ActiveRecord class.
* It then uses CGridView to display every attribute in every <code>Post</code> instance.
* The displayed table is equiped with sorting and pagination functionality.
*
* In order to selectively display attributes with different formats, we may configure the
* {@link CGridView::columns} property. For example, we may specify only the <code>title</code>
* and <code>create_time</code> attributes to be displayed, and the <code>create_time</code>
* should be properly formatted to show as a time. We may also display the attributes of the related
* objects using the dot-syntax as shown below:
*
* <pre>
* $this->widget('zii.widgets.grid.CGridView', array(
* 'dataProvider'=>$dataProvider,
* 'columns'=>array(
* 'title', // display the 'title' attribute
* 'category.name', // display the 'name' attribute of the 'category' relation
* 'content:html', // display the 'content' attribute as purified HTML
* array( // display 'create_time' using an expression
* 'name'=>'create_time',
* 'value'=>'date("M j, Y", $data->create_time)',
* ),
* array( // display 'author.username' using an expression
* 'name'=>'authorName',
* 'value'=>'$data->author->username',
* ),
* array( // display a column with "view", "update" and "delete" buttons
* 'class'=>'CButtonColumn',
* ),
* ),
* ));
* </pre>
*
* Please refer to {@link columns} for more details about how to configure this property.
*
* @property boolean $hasFooter Whether the table should render a footer.
* This is true if any of the {@link columns} has a true {@link CGridColumn::hasFooter} value.
* @property CFormatter $formatter The formatter instance. Defaults to the 'format' application component.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets.grid
* @since 1.1
*/
class CGridView extends CBaseListView
{
const FILTER_POS_HEADER='header';
const FILTER_POS_FOOTER='footer';
const FILTER_POS_BODY='body';
private $_formatter;
/**
* @var array grid column configuration. Each array element represents the configuration
* for one particular grid column which can be either a string or an array.
*
* When a column is specified as a string, it should be in the format of "name:type:header",
* where "type" and "header" are optional. A {@link CDataColumn} instance will be created in this case,
* whose {@link CDataColumn::name}, {@link CDataColumn::type} and {@link CDataColumn::header}
* properties will be initialized accordingly.
*
* When a column is specified as an array, it will be used to create a grid column instance, where
* the 'class' element specifies the column class name (defaults to {@link CDataColumn} if absent).
* Currently, these official column classes are provided: {@link CDataColumn},
* {@link CLinkColumn}, {@link CButtonColumn} and {@link CCheckBoxColumn}.
*/
public $columns=array();
/**
* @var array the CSS class names for the table body rows. If multiple CSS class names are given,
* they will be assigned to the rows sequentially and repeatedly. This property is ignored
* if {@link rowCssClassExpression} is set. Defaults to <code>array('odd', 'even')</code>.
* @see rowCssClassExpression
*/
public $rowCssClass=array('odd','even');
/**
* @var string a PHP expression that is evaluated for every table body row and whose result
* is used as the CSS class name for the row. In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based)</li>
* <li><code>$data</code> the data model for the row</li>
* <li><code>$this</code> the grid view object</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
* @see rowCssClass
* @deprecated in 1.1.13 in favor of {@link rowHtmlOptionsExpression}
*/
public $rowCssClassExpression;
/**
* @var string a PHP expression that is evaluated for every table body row and whose result
* is used as additional HTML attributes for the row. The expression should return an
* array whose key value pairs correspond to html attribute and value.
* In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based)</li>
* <li><code>$data</code> the data model for the row</li>
* <li><code>$this</code> the grid view object</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
* @since 1.1.13
*/
public $rowHtmlOptionsExpression;
/**
* @var boolean whether to display the table even when there is no data. Defaults to true.
* The {@link emptyText} will be displayed to indicate there is no data.
*/
public $showTableOnEmpty=true;
/**
* @var mixed the ID of the container whose content may be updated with an AJAX response.
* Defaults to null, meaning the container for this grid view instance.
* If it is set false, it means sorting and pagination will be performed in normal page requests
* instead of AJAX requests. If the sorting and pagination should trigger the update of multiple
* containers' content in AJAX fashion, these container IDs may be listed here (separated with comma).
*/
public $ajaxUpdate;
/**
* @var string the jQuery selector of the HTML elements that may trigger AJAX updates when they are clicked.
* These tokens are recognized: {page} and {sort}. They will be replaced with the pagination and sorting links selectors.
* Defaults to '{page}, {sort}', that means that the pagination links and the sorting links will trigger AJAX updates.
* Tokens are available from 1.1.11
*
* Note: if this value is empty an exception will be thrown.
*
* Example (adding a custom selector to the default ones):
* <pre>
* ...
* 'updateSelector'=>'{page}, {sort}, #mybutton',
* ...
* </pre>
* @since 1.1.7
*/
public $updateSelector='{page}, {sort}';
/**
* @var string a javascript function that will be invoked if an AJAX update error occurs.
*
* The function signature is <code>function(xhr, textStatus, errorThrown, errorMessage)</code>
* <ul>
* <li><code>xhr</code> is the XMLHttpRequest object.</li>
* <li><code>textStatus</code> is a string describing the type of error that occurred.
* Possible values (besides null) are "timeout", "error", "notmodified" and "parsererror"</li>
* <li><code>errorThrown</code> is an optional exception object, if one occurred.</li>
* <li><code>errorMessage</code> is the CGridView default error message derived from xhr and errorThrown.
* Usefull if you just want to display this error differently. CGridView by default displays this error with an javascript.alert()</li>
* </ul>
* Note: This handler is not called for JSONP requests, because they do not use an XMLHttpRequest.
*
* Example (add in a call to CGridView):
* <pre>
* ...
* 'ajaxUpdateError'=>'function(xhr,ts,et,err){ $("#myerrordiv").text(err); }',
* ...
* </pre>
*/
public $ajaxUpdateError;
/**
* @var string the name of the GET variable that indicates the request is an AJAX request triggered
* by this widget. Defaults to 'ajax'. This is effective only when {@link ajaxUpdate} is not false.
*/
public $ajaxVar='ajax';
/**
* @var mixed the URL for the AJAX requests should be sent to. {@link CHtml::normalizeUrl()} will be
* called on this property. If not set, the current page URL will be used for AJAX requests.
* @since 1.1.8
*/
public $ajaxUrl;
/**
* @var string the type ('GET' or 'POST') of the AJAX requests. If not set, 'GET' will be used.
* You can set this to 'POST' if you are filtering by many fields at once and have a problem with GET query string length.
* Note that in POST mode direct links and {@link enableHistory} feature may not work correctly!
* @since 1.1.14
*/
public $ajaxType;
/**
* @var string a javascript function that will be invoked before an AJAX update occurs.
* The function signature is <code>function(id,options)</code> where 'id' refers to the ID of the grid view,
* 'options' the AJAX request options (see jQuery.ajax api manual).
*/
public $beforeAjaxUpdate;
/**
* @var string a javascript function that will be invoked after a successful AJAX response is received.
* The function signature is <code>function(id, data)</code> where 'id' refers to the ID of the grid view,
* 'data' the received ajax response data.
*/
public $afterAjaxUpdate;
/**
* @var string a javascript function that will be invoked after the row selection is changed.
* The function signature is <code>function(id)</code> where 'id' refers to the ID of the grid view.
* In this function, you may use <code>$(gridID).yiiGridView('getSelection')</code> to get the key values
* of the currently selected rows (gridID is the DOM selector of the grid).
* @see selectableRows
*/
public $selectionChanged;
/**
* @var integer the number of table body rows that can be selected. If 0, it means rows cannot be selected.
* If 1, only one row can be selected. If 2 or any other number, it means multiple rows can be selected.
* A selected row will have a CSS class named 'selected'. You may also call the JavaScript function
* <code>$(gridID).yiiGridView('getSelection')</code> to retrieve the key values of the currently selected
* rows (gridID is the DOM selector of the grid).
*/
public $selectableRows=1;
/**
* @var string the base script URL for all grid view resources (eg javascript, CSS file, images).
* Defaults to null, meaning using the integrated grid view resources (which are published as assets).
*/
public $baseScriptUrl;
/**
* @var string the URL of the CSS file used by this grid view. Defaults to null, meaning using the integrated
* CSS file. If this is set false, you are responsible to explicitly include the necessary CSS file in your page.
*/
public $cssFile;
/**
* @var string the text to be displayed in a data cell when a data value is null. This property will NOT be HTML-encoded
* when rendering. Defaults to an HTML blank.
*/
public $nullDisplay='&nbsp;';
/**
* @var string the text to be displayed in an empty grid cell. This property will NOT be HTML-encoded when rendering. Defaults to an HTML blank.
* This differs from {@link nullDisplay} in that {@link nullDisplay} is only used by {@link CDataColumn} to render
* null data values.
* @since 1.1.7
*/
public $blankDisplay='&nbsp;';
/**
* @var string the CSS class name that will be assigned to the widget container element
* when the widget is updating its content via AJAX. Defaults to 'grid-view-loading'.
* @since 1.1.1
*/
public $loadingCssClass='grid-view-loading';
/**
* @var string the jQuery selector of filter input fields.
* The token '{filter}' is recognized and it will be replaced with the grid filters selector.
* Defaults to '{filter}'.
*
* Note: if this value is empty an exception will be thrown.
*
* Example (adding a custom selector to the default one):
* <pre>
* ...
* 'filterSelector'=>'{filter}, #myfilter',
* ...
* </pre>
* @since 1.1.13
*/
public $filterSelector='{filter}';
/**
* @var string the CSS class name for the table row element containing all filter input fields. Defaults to 'filters'.
* @see filter
* @since 1.1.1
*/
public $filterCssClass='filters';
/**
* @var string whether the filters should be displayed in the grid view. Valid values include:
* <ul>
* <li>header: the filters will be displayed on top of each column's header cell.</li>
* <li>body: the filters will be displayed right below each column's header cell.</li>
* <li>footer: the filters will be displayed below each column's footer cell.</li>
* </ul>
* @see filter
* @since 1.1.1
*/
public $filterPosition='body';
/**
* @var CModel the model instance that keeps the user-entered filter data. When this property is set,
* the grid view will enable column-based filtering. Each data column by default will display a text field
* at the top that users can fill in to filter the data.
* Note that in order to show an input field for filtering, a column must have its {@link CDataColumn::name}
* property set or have {@link CDataColumn::filter} as the HTML code for the input field.
* When this property is not set (null) the filtering is disabled.
* @since 1.1.1
*/
public $filter;
/**
* @var boolean whether to hide the header cells of the grid. When this is true, header cells
* will not be rendered, which means the grid cannot be sorted anymore since the sort links are located
* in the header. Defaults to false.
* @since 1.1.1
*/
public $hideHeader=false;
/**
* @var boolean whether to leverage the {@link https://developer.mozilla.org/en/DOM/window.history DOM history object}. Set this property to true
* to persist state of grid across page revisits. Note, there are two limitations for this feature:
* <ul>
* <li>this feature is only compatible with browsers that support HTML5.</li>
* <li>expect unexpected functionality (e.g. multiple ajax calls) if there is more than one grid/list on a single page with enableHistory turned on.</li>
* </ul>
* @since 1.1.11
*/
public $enableHistory=false;
/**
* Initializes the grid view.
* This method will initialize required property values and instantiate {@link columns} objects.
*/
public function init()
{
parent::init();
if(empty($this->updateSelector))
throw new CException(Yii::t('zii','The property updateSelector should be defined.'));
if(empty($this->filterSelector))
throw new CException(Yii::t('zii','The property filterSelector should be defined.'));
if(!isset($this->htmlOptions['class']))
$this->htmlOptions['class']='grid-view';
if($this->baseScriptUrl===null)
$this->baseScriptUrl=Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('zii.widgets.assets')).'/gridview';
if($this->cssFile!==false)
{
if($this->cssFile===null)
$this->cssFile=$this->baseScriptUrl.'/styles.css';
Yii::app()->getClientScript()->registerCssFile($this->cssFile);
}
$this->initColumns();
}
/**
* Creates column objects and initializes them.
*/
protected function initColumns()
{
if($this->columns===array())
{
if($this->dataProvider instanceof CActiveDataProvider)
$this->columns=$this->dataProvider->model->attributeNames();
elseif($this->dataProvider instanceof IDataProvider)
{
// use the keys of the first row of data as the default columns
$data=$this->dataProvider->getData();
if(isset($data[0]) && is_array($data[0]))
$this->columns=array_keys($data[0]);
}
}
$id=$this->getId();
foreach($this->columns as $i=>$column)
{
if(is_string($column))
$column=$this->createDataColumn($column);
else
{
if(!isset($column['class']))
$column['class']='CDataColumn';
$column=Yii::createComponent($column, $this);
}
if(!$column->visible)
{
unset($this->columns[$i]);
continue;
}
if($column->id===null)
$column->id=$id.'_c'.$i;
$this->columns[$i]=$column;
}
foreach($this->columns as $column)
$column->init();
}
/**
* Creates a {@link CDataColumn} based on a shortcut column specification string.
* @param string $text the column specification string
* @return CDataColumn the column instance
*/
protected function createDataColumn($text)
{
if(!preg_match('/^([\w\.]+)(:(\w*))?(:(.*))?$/',$text,$matches))
throw new CException(Yii::t('zii','The column must be specified in the format of "Name:Type:Label", where "Type" and "Label" are optional.'));
$column=new CDataColumn($this);
$column->name=$matches[1];
if(isset($matches[3]) && $matches[3]!=='')
$column->type=$matches[3];
if(isset($matches[5]))
$column->header=$matches[5];
return $column;
}
/**
* Registers necessary client scripts.
*/
public function registerClientScript()
{
$id=$this->getId();
if($this->ajaxUpdate===false)
$ajaxUpdate=false;
else
$ajaxUpdate=array_unique(preg_split('/\s*,\s*/',$this->ajaxUpdate.','.$id,-1,PREG_SPLIT_NO_EMPTY));
$options=array(
'ajaxUpdate'=>$ajaxUpdate,
'ajaxVar'=>$this->ajaxVar,
'pagerClass'=>$this->pagerCssClass,
'loadingClass'=>$this->loadingCssClass,
'filterClass'=>$this->filterCssClass,
'tableClass'=>$this->itemsCssClass,
'selectableRows'=>$this->selectableRows,
'enableHistory'=>$this->enableHistory,
'updateSelector'=>$this->updateSelector,
'filterSelector'=>$this->filterSelector
);
if($this->ajaxUrl!==null)
$options['url']=CHtml::normalizeUrl($this->ajaxUrl);
if($this->ajaxType!==null)
$options['ajaxType']=strtoupper($this->ajaxType);
if($this->enablePagination)
$options['pageVar']=$this->dataProvider->getPagination()->pageVar;
foreach(array('beforeAjaxUpdate', 'afterAjaxUpdate', 'ajaxUpdateError', 'selectionChanged') as $event)
{
if($this->$event!==null)
{
if($this->$event instanceof CJavaScriptExpression)
$options[$event]=$this->$event;
else
$options[$event]=new CJavaScriptExpression($this->$event);
}
}
$options=CJavaScript::encode($options);
$cs=Yii::app()->getClientScript();
$cs->registerCoreScript('jquery');
$cs->registerCoreScript('bbq');
if($this->enableHistory)
$cs->registerCoreScript('history');
$cs->registerScriptFile($this->baseScriptUrl.'/jquery.yiigridview.js',CClientScript::POS_END);
$cs->registerScript(__CLASS__.'#'.$id,"jQuery('#$id').yiiGridView($options);");
}
/**
* Renders the data items for the grid view.
*/
public function renderItems()
{
if($this->dataProvider->getItemCount()>0 || $this->showTableOnEmpty)
{
echo "<table class=\"{$this->itemsCssClass}\">\n";
$this->renderTableHeader();
ob_start();
$this->renderTableBody();
$body=ob_get_clean();
$this->renderTableFooter();
echo $body; // TFOOT must appear before TBODY according to the standard.
echo "</table>";
}
else
$this->renderEmptyText();
}
/**
* Renders the table header.
*/
public function renderTableHeader()
{
if(!$this->hideHeader)
{
echo "<thead>\n";
if($this->filterPosition===self::FILTER_POS_HEADER)
$this->renderFilter();
echo "<tr>\n";
foreach($this->columns as $column)
$column->renderHeaderCell();
echo "</tr>\n";
if($this->filterPosition===self::FILTER_POS_BODY)
$this->renderFilter();
echo "</thead>\n";
}
elseif($this->filter!==null && ($this->filterPosition===self::FILTER_POS_HEADER || $this->filterPosition===self::FILTER_POS_BODY))
{
echo "<thead>\n";
$this->renderFilter();
echo "</thead>\n";
}
}
/**
* Renders the filter.
* @since 1.1.1
*/
public function renderFilter()
{
if($this->filter!==null)
{
echo "<tr class=\"{$this->filterCssClass}\">\n";
foreach($this->columns as $column)
$column->renderFilterCell();
echo "</tr>\n";
}
}
/**
* Renders the table footer.
*/
public function renderTableFooter()
{
$hasFilter=$this->filter!==null && $this->filterPosition===self::FILTER_POS_FOOTER;
$hasFooter=$this->getHasFooter();
if($hasFilter || $hasFooter)
{
echo "<tfoot>\n";
if($hasFooter)
{
echo "<tr>\n";
foreach($this->columns as $column)
$column->renderFooterCell();
echo "</tr>\n";
}
if($hasFilter)
$this->renderFilter();
echo "</tfoot>\n";
}
}
/**
* Renders the table body.
*/
public function renderTableBody()
{
$data=$this->dataProvider->getData();
$n=count($data);
echo "<tbody>\n";
if($n>0)
{
for($row=0;$row<$n;++$row)
$this->renderTableRow($row);
}
else
{
echo '<tr><td colspan="'.count($this->columns).'" class="empty">';
$this->renderEmptyText();
echo "</td></tr>\n";
}
echo "</tbody>\n";
}
/**
* Renders a table body row.
* @param integer $row the row number (zero-based).
*/
public function renderTableRow($row)
{
$htmlOptions=array();
if($this->rowHtmlOptionsExpression!==null)
{
$data=$this->dataProvider->data[$row];
$options=$this->evaluateExpression($this->rowHtmlOptionsExpression,array('row'=>$row,'data'=>$data));
if(is_array($options))
$htmlOptions = $options;
}
if($this->rowCssClassExpression!==null)
{
$data=$this->dataProvider->data[$row];
$class=$this->evaluateExpression($this->rowCssClassExpression,array('row'=>$row,'data'=>$data));
}
elseif(is_array($this->rowCssClass) && ($n=count($this->rowCssClass))>0)
$class=$this->rowCssClass[$row%$n];
if(!empty($class))
{
if(isset($htmlOptions['class']))
$htmlOptions['class'].=' '.$class;
else
$htmlOptions['class']=$class;
}
echo CHtml::openTag('tr', $htmlOptions)."\n";
foreach($this->columns as $column)
$column->renderDataCell($row);
echo "</tr>\n";
}
/**
* @return boolean whether the table should render a footer.
* This is true if any of the {@link columns} has a true {@link CGridColumn::hasFooter} value.
*/
public function getHasFooter()
{
foreach($this->columns as $column)
if($column->getHasFooter())
return true;
return false;
}
/**
* @return CFormatter the formatter instance. Defaults to the 'format' application component.
*/
public function getFormatter()
{
if($this->_formatter===null)
$this->_formatter=Yii::app()->format;
return $this->_formatter;
}
/**
* @param CFormatter $value the formatter instance
*/
public function setFormatter($value)
{
$this->_formatter=$value;
}
}

View File

@@ -0,0 +1,111 @@
<?php
/**
* CLinkColumn class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.grid.CGridColumn');
/**
* CLinkColumn represents a grid view column that renders a hyperlink in each of its data cells.
*
* The {@link label} and {@link url} properties determine how each hyperlink will be rendered.
* The {@link labelExpression}, {@link urlExpression} properties may be used instead if they are available.
* In addition, if {@link imageUrl} is set, an image link will be rendered.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets.grid
* @since 1.1
*/
class CLinkColumn extends CGridColumn
{
/**
* @var string the label to the hyperlinks in the data cells. Note that the label will not
* be HTML-encoded when rendering. This property is ignored if {@link labelExpression} is set.
* @see labelExpression
*/
public $label='Link';
/**
* @var string a PHP expression that will be evaluated for every data cell and whose result will be rendered
* as the label of the hyperlink of the data cell.
* In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based).</li>
* <li><code>$data</code> the data model for the row.</li>
* <li><code>$this</code> the column object.</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*/
public $labelExpression;
/**
* @var string the URL to the image. If this is set, an image link will be rendered.
*/
public $imageUrl;
/**
* @var string the URL of the hyperlinks in the data cells.
* This property is ignored if {@link urlExpression} is set.
* @see urlExpression
*/
public $url='javascript:void(0)';
/**
* @var string a PHP expression that will be evaluated for every data cell and whose result will be rendered
* as the URL of the hyperlink of the data cells.
* In this expression, you can use the following variables:
* <ul>
* <li><code>$row</code> the row number (zero-based).</li>
* <li><code>$data</code> the data model for the row.</li>
* <li><code>$this</code> the column object.</li>
* </ul>
* The PHP expression will be evaluated using {@link evaluateExpression}.
*
* A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
* please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
*/
public $urlExpression;
/**
* @var array the HTML options for the data cell tags.
*/
public $htmlOptions=array('class'=>'link-column');
/**
* @var array the HTML options for the header cell tag.
*/
public $headerHtmlOptions=array('class'=>'link-column');
/**
* @var array the HTML options for the footer cell tag.
*/
public $footerHtmlOptions=array('class'=>'link-column');
/**
* @var array the HTML options for the hyperlinks
*/
public $linkHtmlOptions=array();
/**
* Renders the data cell content.
* This method renders a hyperlink in the data cell.
* @param integer $row the row number (zero-based)
* @param mixed $data the data associated with the row
*/
protected function renderDataCellContent($row,$data)
{
if($this->urlExpression!==null)
$url=$this->evaluateExpression($this->urlExpression,array('data'=>$data,'row'=>$row));
else
$url=$this->url;
if($this->labelExpression!==null)
$label=$this->evaluateExpression($this->labelExpression,array('data'=>$data,'row'=>$row));
else
$label=$this->label;
$options=$this->linkHtmlOptions;
if(is_string($this->imageUrl))
echo CHtml::link(CHtml::image($this->imageUrl,$label),$url,$options);
else
echo CHtml::link($label,$url,$options);
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* CJuiAccordion class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiAccordion displays an accordion widget.
*
* CJuiAccordion encapsulates the {@link http://jqueryui.com/accordion/ JUI Accordion}
* plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiAccordion',array(
* 'panels'=>array(
* 'panel 1'=>'content for panel 1',
* 'panel 2'=>'content for panel 2',
* // panel 3 contains the content rendered by a partial view
* 'panel 3'=>$this->renderPartial('_partial',null,true),
* ),
* // additional javascript options for the accordion plugin
* 'options'=>array(
* 'animated'=>'bounceslide',
* ),
* ));
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI accordion plugin. Please refer to
* the {@link http://api.jqueryui.com/accordion/ JUI Accordion API}
* documentation for possible options (name-value pairs) and
* {@link http://jqueryui.com/accordion/ JUI Accordion page} for general
* description and demo.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiAccordion extends CJuiWidget
{
/**
* @var array list of panels (panel title=>panel content).
* Note that neither panel title nor panel content will be HTML-encoded.
*/
public $panels=array();
/**
* @var string the name of the container element that contains all panels. Defaults to 'div'.
*/
public $tagName='div';
/**
* @var string the template that is used to generated every panel header.
* The token "{title}" in the template will be replaced with the panel title.
* Note that if you make change to this template, you may also need to adjust
* the 'header' setting in {@link options}.
*/
public $headerTemplate='<h3><a href="#">{title}</a></h3>';
/**
* @var string the template that is used to generated every panel content.
* The token "{content}" in the template will be replaced with the panel content.
*/
public $contentTemplate='<div>{content}</div>';
/**
* Run this widget.
* This method registers necessary javascript and renders the needed HTML code.
*/
public function run()
{
$id=$this->getId();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
foreach($this->panels as $title=>$content)
{
echo strtr($this->headerTemplate,array('{title}'=>$title))."\n";
echo strtr($this->contentTemplate,array('{content}'=>$content))."\n";
}
echo CHtml::closeTag($this->tagName);
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').accordion($options);");
}
}

View File

@@ -0,0 +1,97 @@
<?php
/**
* CJuiAutoComplete class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiInputWidget');
/**
* CJuiAutoComplete displays an autocomplete field.
*
* CJuiAutoComplete encapsulates the {@link http://jqueryui.com/autocomplete/ JUI
* autocomplete} plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiAutoComplete',array(
* 'name'=>'city',
* 'source'=>array('ac1','ac2','ac3'),
* // additional javascript options for the autocomplete plugin
* 'options'=>array(
* 'minLength'=>'2',
* ),
* 'htmlOptions'=>array(
* 'style'=>'height:20px;',
* ),
* ));
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI autocomplete plugin. Please refer to
* the {@link http://api.jqueryui.com/autocomplete/ JUI AutoComplete API}
* documentation for possible options (name-value pairs) and
* {@link http://jqueryui.com/autocomplete/ JUI AutoComplete page} for
* general description and demo.
*
* By configuring the {@link source} property, you may specify where to search
* the autocomplete options for each item. If source is an array, the list is
* used for autocomplete. You may also configure {@link sourceUrl} to retrieve
* autocomplete items from an ajax response.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1.2
*/
class CJuiAutoComplete extends CJuiInputWidget
{
/**
* @var mixed the entries that the autocomplete should choose from. This can be
* <ul>
* <li>an Array with local data</li>
* <li>a String, specifying a URL that returns JSON data as the entries.</li>
* <li>a javascript callback. Please make sure you wrap the callback with
* {@link CJavaScriptExpression} in this case.</li>
* </ul>
*/
public $source=array();
/**
* @var mixed the URL that will return JSON data as the autocomplete items.
* CHtml::normalizeUrl() will be applied to this property to convert the property
* into a proper URL. When this property is set, the {@link source} property will be ignored.
*/
public $sourceUrl;
/**
* Run this widget.
* This method registers necessary javascript and renders the needed HTML code.
*/
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'];
if($this->hasModel())
echo CHtml::activeTextField($this->model,$this->attribute,$this->htmlOptions);
else
echo CHtml::textField($name,$this->value,$this->htmlOptions);
if($this->sourceUrl!==null)
$this->options['source']=CHtml::normalizeUrl($this->sourceUrl);
else
$this->options['source']=$this->source;
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').autocomplete($options);");
}
}

View File

@@ -0,0 +1,174 @@
<?php
/**
* CJuiButton class file.
*
* @author Sebastian Thierer <sebas@artfos.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiInputWidget');
/**
* CJuiButton displays a button widget.
*
* CJuiButton encapsulates the {@link http://jqueryui.com/button/ JUI Button}
* plugin.
*
* To use this widget as a submit button, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiButton',array(
* 'buttonType'=>'submit',
* 'name'=>'btnSubmit',
* 'value'=>'1',
* 'caption'=>'Submit form',
* 'htmlOptions'=>array('class'=>'ui-button-primary')
* ),
* ));
* </pre>
*
* To use this widget as a button, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiButton',array(
* 'buttonType'=>'button',
* 'name'=>'btnSave',
* 'caption'=>'Save',
* 'onclick'=>new CJavaScriptExpression('function(){alert("Save button clicked"); this.blur(); return false;}'),
* ));
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI button plugin. Please refer to
* the {@link http://api.jqueryui.com/button/ JUI Button API} documentation
* for possible options (name-value pairs) and
* {@link http://jqueryui.com/button/ JUI Button page} for general description
* and demo.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1.3
*/
class CJuiButton extends CJuiInputWidget
{
/**
* @var string The button type (possible types: submit, button, link, radio, checkbox, buttonset).
* "submit" is used as default.
*/
public $buttonType='submit';
/**
* @var string The default html tag for the buttonset
*/
public $htmlTag='div';
/**
* @var mixed a URL or an action route that can be used to create a URL. Used when a buttonType "link" is selected.
* See {@link normalizeUrl} for more details about how to specify this parameter.
*/
public $url=null;
/**
* @var mixed The value of the current item. Used only for "radio" and "checkbox"
*/
public $value;
/**
* @var string The button text
*/
public $caption="";
/**
* @var string The javascript function to be raised when this item is clicked (client event).
*/
public $onclick;
/**
* (non-PHPdoc)
* @see framework/zii/widgets/jui/CJuiWidget::init()
*/
public function init()
{
parent::init();
if($this->buttonType=='buttonset')
{
if(!isset($this->htmlOptions['id']))
$this->htmlOptions['id']=$this->getId();
echo CHtml::openTag($this->htmlTag,$this->htmlOptions);
}
}
/**
* (non-PHPdoc)
* @see framework/CWidget::run()
*/
public function run()
{
$cs=Yii::app()->getClientScript();
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'];
else
$this->htmlOptions['name']=$name;
if($this->buttonType=='buttonset')
{
echo CHtml::closeTag($this->htmlTag);
$cs->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').buttonset();");
}
else
{
switch($this->buttonType)
{
case 'submit':
echo CHtml::submitButton($this->caption,$this->htmlOptions)."\n";
break;
case 'button':
echo CHtml::htmlButton($this->caption,$this->htmlOptions)."\n";
break;
case 'link':
echo CHtml::link($this->caption,$this->url,$this->htmlOptions)."\n";
break;
case 'radio':
if($this->hasModel())
{
echo CHtml::activeRadioButton($this->model,$this->attribute,$this->htmlOptions);
echo CHtml::label($this->caption,CHtml::activeId($this->model,$this->attribute))."\n";
}
else
{
echo CHtml::radioButton($name,$this->value,$this->htmlOptions);
echo CHtml::label($this->caption,$id)."\n";
}
break;
case 'checkbox':
if($this->hasModel())
{
echo CHtml::activeCheckbox($this->model,$this->attribute,$this->htmlOptions);
echo CHtml::label($this->caption,CHtml::activeId($this->model,$this->attribute))."\n";
}
else
{
echo CHtml::checkbox($name,$this->value,$this->htmlOptions);
echo CHtml::label($this->caption,$id)."\n";
}
break;
default:
throw new CException(Yii::t('zii','The button type "{type}" is not supported.',array('{type}'=>$this->buttonType)));
}
$options=CJavaScript::encode($this->options);
if($this->onclick!==null)
{
if(!($this->onclick instanceof CJavaScriptExpression))
$this->onclick=new CJavaScriptExpression($this->onclick);
$click=CJavaScript::encode($this->onclick);
$cs->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').button($options).click($click);");
}
else
$cs->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').button($options);");
}
}
}

View File

@@ -0,0 +1,128 @@
<?php
/**
* CJuiDatePicker class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiInputWidget');
/**
* CJuiDatePicker displays a datepicker.
*
* CJuiDatePicker encapsulates the {@link http://jqueryui.com/datepicker/ JUI
* datepicker} plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiDatePicker',array(
* 'name'=>'publishDate',
* // additional javascript options for the date picker plugin
* 'options'=>array(
* 'showAnim'=>'fold',
* ),
* 'htmlOptions'=>array(
* 'style'=>'height:20px;'
* ),
* ));
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI datepicker plugin. Please refer to
* the {@link http://api.jqueryui.com/datepicker/ JUI DatePicker API}
* documentation for possible options (name-value pairs) and
* {@link http://jqueryui.com/datepicker/ JUI DatePicker page} for general
* description and demo.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiDatePicker extends CJuiInputWidget
{
/**
* @var string the locale ID (eg 'fr', 'de') for the language to be used by the date picker.
* If this property is not set, I18N will not be involved. That is, the date picker will show in English.
* You can force English language by setting the language attribute as '' (empty string)
*/
public $language;
/**
* @var string The i18n Jquery UI script file. It uses scriptUrl property as base url.
*/
public $i18nScriptFile='jquery-ui-i18n.min.js';
/**
* @var array The default options called just one time per request. This options will alter every other CJuiDatePicker instance in the page.
* It has to be set at the first call of CJuiDatePicker widget in the request.
*/
public $defaultOptions;
/**
* @var boolean If true, shows the widget as an inline calendar and the input as a hidden field.
*/
public $flat=false;
/**
* Run this widget.
* This method registers necessary javascript and renders the needed HTML code.
*/
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'];
if($this->flat===false)
{
if($this->hasModel())
echo CHtml::activeTextField($this->model,$this->attribute,$this->htmlOptions);
else
echo CHtml::textField($name,$this->value,$this->htmlOptions);
}
else
{
if($this->hasModel())
{
echo CHtml::activeHiddenField($this->model,$this->attribute,$this->htmlOptions);
$attribute=$this->attribute;
$this->options['defaultDate']=$this->model->$attribute;
}
else
{
echo CHtml::hiddenField($name,$this->value,$this->htmlOptions);
$this->options['defaultDate']=$this->value;
}
$this->options['altField']='#'.$id;
$id=$this->htmlOptions['id']=$id.'_container';
$this->htmlOptions['name']=$name.'_container';
echo CHtml::tag('div',$this->htmlOptions,'');
}
$options=CJavaScript::encode($this->options);
$js = "jQuery('#{$id}').datepicker($options);";
if($this->language!='' && $this->language!='en')
{
$this->registerScriptFile($this->i18nScriptFile);
$js = "jQuery('#{$id}').datepicker(jQuery.extend({showMonthAfterYear:false},jQuery.datepicker.regional['{$this->language}'],{$options}));";
}
$cs = Yii::app()->getClientScript();
if(isset($this->defaultOptions))
{
$this->registerScriptFile($this->i18nScriptFile);
$cs->registerScript(__CLASS__,$this->defaultOptions!==null?'jQuery.datepicker.setDefaults('.CJavaScript::encode($this->defaultOptions).');':'');
}
$cs->registerScript(__CLASS__.'#'.$id,$js);
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* CJuiDialog class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiDialog displays a dialog widget.
*
* CJuiDialog encapsulates the {@link http://jqueryui.com/dialog/ JUI Dialog}
* plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->beginWidget('zii.widgets.jui.CJuiDialog',array(
* 'id'=>'mydialog',
* // additional javascript options for the dialog plugin
* 'options'=>array(
* 'title'=>'Dialog box 1',
* 'autoOpen'=>false,
* ),
* ));
*
* echo 'dialog content here';
*
* $this->endWidget('zii.widgets.jui.CJuiDialog');
*
* // the link that may open the dialog
* echo CHtml::link('open dialog', '#', array(
* 'onclick'=>'$("#mydialog").dialog("open"); return false;',
* ));
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI dialog plugin. Please refer to
* the {@link http://api.jqueryui.com/dialog/ JUI Dialog API} documentation
* for possible options (name-value pairs) and
* {@link http://jqueryui.com/dialog/ JUI Dialog page} for general description
* and demo.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiDialog extends CJuiWidget
{
/**
* @var string the name of the container element that contains all panels. Defaults to 'div'.
*/
public $tagName='div';
/**
* Renders the open tag of the dialog.
* This method also registers the necessary javascript code.
*/
public function init()
{
parent::init();
$id=$this->getId();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').dialog($options);");
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
}
/**
* Renders the close tag of the dialog.
*/
public function run()
{
echo CHtml::closeTag($this->tagName);
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* CJuiDraggable class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiDraggable displays a draggable widget.
*
* CJuiDraggable encapsulates the {@link http://jqueryui.com/draggable/ JUI Draggable}
* plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->beginWidget('zii.widgets.jui.CJuiDraggable',array(
* // additional javascript options for the draggable plugin
* 'options'=>array(
* 'scope'=>'myScope',
* ),
* ));
* echo 'Your draggable content here';
*
* $this->endWidget();
*
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI Draggable plugin. Please refer to
* the {@link http://api.jqueryui.com/draggable/ JUI Draggable API} documentation
* for possible options (name-value pairs) and
* {@link http://jqueryui.com/draggable/ JUI Draggable page} for general
* description and demo.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiDraggable extends CJuiWidget
{
/**
* @var string the name of the Draggable element. Defaults to 'div'.
*/
public $tagName='div';
/**
* Renders the open tag of the draggable element.
* This method also registers the necessary javascript code.
*/
public function init()
{
parent::init();
$id=$this->getId();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').draggable($options);");
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
}
/**
* Renders the close tag of the draggable element.
*/
public function run()
{
echo CHtml::closeTag($this->tagName);
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* CJuiDroppable class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiDroppable displays a droppable widget.
*
* CJuiDroppable encapsulates the {@link http://jqueryui.com/droppable/ JUI Droppable}
* plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->beginWidget('zii.widgets.jui.CJuiDroppable',array(
* // additional javascript options for the droppable plugin
* 'options'=>array(
* 'scope'=>'myScope',
* ),
* ));
* echo 'Your droppable content here';
*
* $this->endWidget();
*
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI Droppable plugin. Please refer to
* the {@link http://api.jqueryui.com/droppable/ JUI Droppable API} documentation
* for possible options (name-value pairs) and
* {@link http://jqueryui.com/droppable/ JUI Droppable page} for general
* description and demo.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiDroppable extends CJuiWidget
{
/**
* @var string the HTML tag name of the Droppable element. Defaults to 'div'.
*/
public $tagName='div';
/**
* Renders the open tag of the droppable element.
* This method also registers the necessary javascript code.
*/
public function init()
{
parent::init();
$id=$this->getId();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').droppable($options);");
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
}
/**
* Renders the close tag of the droppable element.
*/
public function run()
{
echo CHtml::closeTag($this->tagName);
}
}

View File

@@ -0,0 +1,80 @@
<?php
/**
* CJuiInputWidget class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiInputWidget is the base class for JUI widgets that can collect user input.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
abstract class CJuiInputWidget extends CJuiWidget
{
/**
* @var CModel the data model associated with this widget.
*/
public $model;
/**
* @var string the attribute associated with this widget.
* The name can contain square brackets (e.g. 'name[1]') which is used to collect tabular data input.
*/
public $attribute;
/**
* @var string the input name. This must be set if {@link model} is not set.
*/
public $name;
/**
* @var string the input value.
*/
public $value;
/**
* Resolves name and ID of the input. Source property of the name and/or source property of the attribute
* could be customized by specifying first and/or second parameter accordingly.
* @param string $nameProperty class property name which holds element name to be used. This parameter
* is available since 1.1.14.
* @param string $attributeProperty class property name which holds model attribute name to be used. This
* parameter is available since 1.1.14.
* @return array name and ID of the input: array('name','id').
* @throws CException in case model and attribute property or name property cannot be resolved.
*/
protected function resolveNameID($nameProperty='name',$attributeProperty='attribute')
{
if($this->$nameProperty!==null)
$name=$this->$nameProperty;
elseif(isset($this->htmlOptions[$nameProperty]))
$name=$this->htmlOptions[$nameProperty];
elseif($this->hasModel())
$name=CHtml::activeName($this->model,$this->$attributeProperty);
else
throw new CException(Yii::t('zii','{class} must specify "model" and "{attribute}" or "{name}" property values.',
array('{class}'=>get_class($this),'{attribute}'=>$attributeProperty,'{name}'=>$nameProperty)));
if(($id=$this->getId(false))===null)
{
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$id=CHtml::getIdByName($name);
}
return array($name,$id);
}
/**
* @return boolean whether this widget is associated with a data model.
*/
protected function hasModel()
{
return $this->model instanceof CModel && $this->attribute!==null;
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* CJuiProgressBar class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiProgressBar displays a progress bar widget.
*
* CJuiProgressBar encapsulates the {@link http://jqueryui.com/progressbar/ JUI
* Progressbar} plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiProgressBar',array(
* 'value'=>75,
* // additional javascript options for the progress bar plugin
* 'options'=>array(
* 'change'=>new CJavaScriptExpression('function(event, ui) {...}'),
* ),
* 'htmlOptions'=>array(
* 'style'=>'height:20px;',
* ),
* ));
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI progressbar plugin. Please refer to
* the {@link http://api.jqueryui.com/progressbar/ JUI ProgressBar} documentation
* for possible options (name-value pairs) and
* {@link http://jqueryui.com/progressbar/ JUI ProgressBar page} for general
* description and demo.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiProgressBar extends CJuiWidget
{
/**
* @var string the name of the container element that contains the progress bar. Defaults to 'div'.
*/
public $tagName='div';
/**
* @var integer the percentage of the progress. This must be an integer between 0 and 100. Defaults to 0.
*/
public $value=0;
/**
* Run this widget.
* This method registers necessary javascript and renders the needed HTML code.
*/
public function run()
{
$id=$this->getId();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
echo CHtml::openTag($this->tagName,$this->htmlOptions);
echo CHtml::closeTag($this->tagName);
$this->options['value']=$this->value;
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').progressbar($options);");
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* CJuiResizable class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiResizable displays a resizable widget.
*
* CJuiResizable encapsulates the {@link http://jqueryui.com/resizable/ JUI Resizable}
* plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->beginWidget('zii.widgets.jui.CJuiResizable',array(
* // additional javascript options for the resizable plugin
* 'options'=>array(
* 'minHeight'=>'150',
* ),
* ));
* echo 'Your Resizable content here';
*
* $this->endWidget();
*
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI Resizable plugin. Please refer to
* the {@link http://api.jqueryui.com/resizable/ JUI Resizable API} documentation
* for possible options (name-value pairs) and
* {@link http://jqueryui.com/resizable/ JUI Resizable page} for general
* description and demo.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiResizable extends CJuiWidget
{
/**
* @var string the name of the Resizable element. Defaults to 'div'.
*/
public $tagName='div';
/**
* Renders the open tag of the resizable element.
* This method also registers the necessary javascript code.
*/
public function init()
{
parent::init();
$id=$this->getId();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').resizable($options);");
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
}
/**
* Renders the close tag of the resizable element.
*/
public function run()
{
echo CHtml::closeTag($this->tagName);
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* CJuiSelectable class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiSelectable displays an accordion widget.
*
* CJuiSelectable encapsulates the {@link http://jqueryui.com/selectable/ JUI Selectable}
* plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiSelectable',array(
* 'items'=>array(
* 'id1'=>'Item 1',
* 'id2'=>'Item 2',
* 'id3'=>'Item 3',
* ),
* // additional javascript options for the selectable plugin
* 'options'=>array(
* 'delay'=>'300',
* ),
* ));
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI Selectable plugin. Please refer to
* the {@link http://api.jqueryui.com/selectable/ JUI Selectable API}
* documentation for possible options (name-value pairs) and
* {@link http://jqueryui.com/selectable/ JUI Selectable page} for general
* description and demo.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiSelectable extends CJuiWidget {
/**
* @var array list of selectable items (id=>item content).
* Note that the item contents will not be HTML-encoded.
*/
public $items=array();
/**
* @var string the name of the container element that contains all items. Defaults to 'ol'.
*/
public $tagName='ol';
/**
* @var string the template that is used to generated every selectable item.
* The token "{content}" in the template will be replaced with the item content,
* while "{id}" will be replaced with the item ID.
*/
public $itemTemplate='<li id="{id}">{content}</li>';
/**
* Run this widget.
* This method registers necessary javascript and renders the needed HTML code.
*/
public function run()
{
$id=$this->getId();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').selectable({$options});");
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
foreach($this->items as $id=>$content)
echo strtr($this->itemTemplate,array('{id}'=>$id,'{content}'=>$content))."\n";
echo CHtml::closeTag($this->tagName);
}
}

View File

@@ -0,0 +1,76 @@
<?php
/**
* CJuiSlider class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiSlider displays a slider.
*
* CJuiSlider encapsulates the {@link http://jqueryui.com/slider/ JUI
* slider} plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiSlider',array(
* 'value'=>37,
* // additional javascript options for the slider plugin
* 'options'=>array(
* 'min'=>10,
* 'max'=>50,
* ),
* 'htmlOptions'=>array(
* 'style'=>'height:20px;',
* ),
* ));
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI slider plugin. Please refer to
* the {@link http://api.jqueryui.com/slider/ JUI Slider API} documentation
* for possible options (name-value pairs) and
* {@link http://jqueryui.com/slider/ JUI Slider page} for general
* description and demo.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiSlider extends CJuiWidget
{
/**
* @var string the name of the container element that contains the slider. Defaults to 'div'.
*/
public $tagName='div';
/**
* @var integer determines the value of the slider, if there's only one handle. If there is more than one handle, determines the value of the first handle.
*/
public $value;
/**
* Run this widget.
* This method registers necessary javascript and renders the needed HTML code.
*/
public function run()
{
$id=$this->getId();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
echo CHtml::tag($this->tagName,$this->htmlOptions,'');
if($this->value!==null)
$this->options['value']=$this->value;
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').slider($options);");
}
}

View File

@@ -0,0 +1,168 @@
<?php
/**
* CJuiSliderInput class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiInputWidget');
/**
* CJuiSliderInput displays a slider. It can be used in forms and post its value.
*
* CJuiSlider encapsulates the {@link http://jqueryui.com/slider/ JUI
* slider} plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiSliderInput',array(
* 'name'=>'rate',
* 'value'=>37,
* // additional javascript options for the slider plugin
* 'options'=>array(
* 'min'=>10,
* 'max'=>50,
* ),
* 'htmlOptions'=>array(
* 'style'=>'height:20px;',
* ),
* ));
* </pre>
*
* The widget can also be used in range mode which uses 2 sliders to set a range.
* In this mode, {@link attribute} and {@link maxAttribute} will define the attribute
* names for the minimum and maximum range values, respectively. For example:
*
* <pre>
* $this->widget('zii.widgets.jui.CJuiSliderInput',array(
* 'model'=>$model,
* 'attribute'=>'timeMin',
* 'maxAttribute'=>'timeMax',
* // additional javascript options for the slider plugin
* 'options'=>array(
* 'range'=>true,
* 'min'=>0,
* 'max'=>24,
* ),
* ));
* </pre>
*
* If you need to use the slider event, please change the event value for 'stop' or 'change'.
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI slider plugin. Please refer to
* the {@link http://api.jqueryui.com/slider/ JUI Slider API} documentation
* for possible options (name-value pairs) and
* {@link http://jqueryui.com/slider/ JUI Slider page} for general
* description and demo.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiSliderInput extends CJuiInputWidget
{
/**
* @var string the name of the container element that contains the slider. Defaults to 'div'.
*/
public $tagName='div';
/**
* @var integer determines the value of the slider, if there's only one handle. If there is more than one handle,
* determines the value of the first handle.
*/
public $value;
/**
* @var string the name of the event where the input will be attached to the slider. It
* can be 'slide', 'stop' or 'change'. If you want to use 'slide' event change $event property to 'change'.
*/
public $event='slide';
/**
* @var string name of attribute for max value if slider is used in range mode.
*/
public $maxAttribute;
/**
* @var string the input name to be used for max value attribute when using slider in range mode.
* This must be set in case {@link model} isn't used.
* @since 1.1.14
*/
public $maxName;
/**
* @var integer determines the max value of the slider, if there's two handles (range mode). Ignored if there's
* only one handle.
* @since 1.1.14
*/
public $maxValue;
/**
* @var string the suffix to be appended to the ID of the max value input element
* when slider used in range mode.
* @since 1.1.14
*/
public $maxIdSuffix='_end';
/**
* Run this widget.
* This method registers necessary javascript and renders the needed HTML code.
*/
public function run()
{
list($name,$id)=$this->resolveNameID();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
$isRange=isset($this->options['range']) && $this->options['range'] &&
$this->options['range']!=='max' && $this->options['range']!=='min';
if($this->hasModel())
{
$attribute=$this->attribute;
if($isRange)
{
$options=$this->htmlOptions;
echo CHtml::activeHiddenField($this->model,$this->attribute,$options);
$options['id'].=$this->maxIdSuffix;
echo CHtml::activeHiddenField($this->model,$this->maxAttribute,$options);
$maxAttribute=$this->maxAttribute;
$this->options['values']=array($this->model->$attribute,$this->model->$maxAttribute);
}
else
{
echo CHtml::activeHiddenField($this->model,$this->attribute,$this->htmlOptions);
$this->options['value']=$this->model->$attribute;
}
}
else
{
if($isRange)
{
list($maxName,$maxId)=$this->resolveNameID('maxName','maxAttribute');
$options=$this->htmlOptions;
echo CHtml::hiddenField($name,$this->value,$options);
$options['id'].=$this->maxIdSuffix;
echo CHtml::hiddenField($maxName,$this->maxValue,$options);
$this->options['values']=array($this->value,$this->maxValue);
}
else
{
echo CHtml::hiddenField($name,$this->value,$this->htmlOptions);
if($this->value!==null)
$this->options['value']=$this->value;
}
}
$idHidden=$this->htmlOptions['id'];
$this->htmlOptions['id']=$idHidden.'_slider';
echo CHtml::tag($this->tagName,$this->htmlOptions,'');
$this->options[$this->event]=$isRange
? new CJavaScriptExpression("function(e,ui){ v=ui.values; jQuery('#{$idHidden}').val(v[0]); jQuery('#{$idHidden}{$this->maxIdSuffix}').val(v[1]); }")
: new CJavaScriptExpression("function(event, ui) { jQuery('#{$idHidden}').val(ui.value); }");
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}_slider').slider($options);");
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* CJuiSortable class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiSortable makes selected elements sortable by dragging with the mouse.
*
* CJuiSortable encapsulates the {@link http://jqueryui.com/sortable/ JUI Sortable}
* plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiSortable',array(
* 'items'=>array(
* 'id1'=>'Item 1',
* 'id2'=>'Item 2',
* 'id3'=>'Item 3',
* ),
* // additional javascript options for the JUI Sortable plugin
* 'options'=>array(
* 'delay'=>'300',
* ),
* ));
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI Sortable plugin. Please refer to
* the {@link http://api.jqueryui.com/sortable/ JUI Sortable API} documentation
* for possible options (name-value pairs) and
* {@link http://jqueryui.com/sortable/ JUI Sortable page} for general
* description and demo.
*
* If you are using JavaScript expressions anywhere in the code, please wrap it
* with {@link CJavaScriptExpression} and Yii will use it as code.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiSortable extends CJuiWidget
{
/**
* @var array list of sortable items (id=>item content).
* Note that the item contents will not be HTML-encoded.
*/
public $items=array();
/**
* @var string the name of the container element that contains all items. Defaults to 'ul'.
*/
public $tagName='ul';
/**
* @var string the template that is used to generated every sortable item.
* The token "{content}" in the template will be replaced with the item content,
* while "{id}" be replaced with the item ID.
*/
public $itemTemplate='<li id="{id}">{content}</li>';
/**
* Run this widget.
* This method registers necessary javascript and renders the needed HTML code.
*/
public function run()
{
$id=$this->getId();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').sortable({$options});");
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
foreach($this->items as $id=>$content)
echo strtr($this->itemTemplate,array('{id}'=>$id,'{content}'=>$content))."\n";
echo CHtml::closeTag($this->tagName);
}
}

View File

@@ -0,0 +1,149 @@
<?php
/**
* CJuiTabs class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('zii.widgets.jui.CJuiWidget');
/**
* CJuiTabs displays a tabs widget.
*
* CJuiTabs encapsulates the {@link http://jqueryui.com/tabs/ JUI tabs}
* plugin.
*
* To use this widget, you may insert the following code in a view:
* <pre>
* $this->widget('zii.widgets.jui.CJuiTabs',array(
* 'tabs'=>array(
* 'StaticTab 1'=>'Content for tab 1',
* 'StaticTab 2'=>array('content'=>'Content for tab 2', 'id'=>'tab2'),
* // panel 3 contains the content rendered by a partial view
* 'AjaxTab'=>array('ajax'=>$ajaxUrl),
* ),
* // additional javascript options for the tabs plugin
* 'options'=>array(
* 'collapsible'=>true,
* ),
* ));
* </pre>
*
* By configuring the {@link options} property, you may specify the options
* that need to be passed to the JUI tabs plugin. Please refer to
* the {@link http://api.jqueryui.com/tabs/ JUI Tabs API} documentation
* for possible options (name-value pairs) and
* {@link http://jqueryui.com/tabs/ JUI Tabs page} for general
* description and demo.
*
* Note, in case you're using &lt;base/&gt; HTML tag you may run into the
* issue when jQuery UI uses altered base URL to load content, but not
* the base URL content was loaded from. (Developer may expect both behavior
* in different cases.) For this occasion consider using absolute URL
* generation as follows:
*
* <pre>
* $this->widget('zii.widgets.jui.CJuiTabs',array(
* 'tabs'=>array(
* 'Dynamic Tab'=>array('ajax'=>$this->createAbsoluteUrl('tab/content/route')),
* ),
* ));
* </pre>
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
class CJuiTabs extends CJuiWidget
{
/**
* @var array list of tabs (tab title=>tab content).
* Note that the tab title will not be HTML-encoded.
* The tab content can be either a string or an array. When it is an array, it can
* be in one of the following two formats:
* <pre>
* array('id'=>'myTabID', 'content'=>'tab content')
* array('id'=>'myTabID', 'ajax'=>URL)
* </pre>
* where the 'id' element is optional. The second format allows the tab content
* to be dynamically fetched from the specified URL via AJAX. The URL can be either
* a string or an array. If an array, it will be normalized into a URL using {@link CHtml::normalizeUrl}.
*/
public $tabs=array();
/**
* @var string the name of the container element that contains all panels. Defaults to 'div'.
*/
public $tagName='div';
/**
* @var string the template that is used to generated every panel title.
* The token "{title}" in the template will be replaced with the panel title and
* the token "{url}" will be replaced with "#TabID" or with the url of the ajax request.
*/
public $headerTemplate='<li><a href="{url}" title="{id}">{title}</a></li>';
/**
* @var string the template that is used to generated every tab content.
* The token "{content}" in the template will be replaced with the panel content
* and the token "{id}" with the tab ID.
*/
public $contentTemplate='<div id="{id}">{content}</div>';
/**
* Run this widget.
* This method registers necessary javascript and renders the needed HTML code.
*/
public function run()
{
$id=$this->getId();
if(isset($this->htmlOptions['id']))
$id=$this->htmlOptions['id'];
else
$this->htmlOptions['id']=$id;
echo CHtml::openTag($this->tagName,$this->htmlOptions)."\n";
$tabsOut="";
$contentOut="";
$tabCount=0;
foreach($this->tabs as $title=>$content)
{
$tabId=(is_array($content) && isset($content['id']))?$content['id']:$id.'_tab_'.$tabCount++;
if(!is_array($content))
{
$tabsOut.=strtr($this->headerTemplate,array('{title}'=>$title,'{url}'=>'#'.$tabId,'{id}'=>'#'.$tabId))."\n";
$contentOut.=strtr($this->contentTemplate,array('{content}'=>$content,'{id}'=>$tabId))."\n";
}
elseif(isset($content['ajax']))
{
$tabsOut.=strtr($this->headerTemplate,array('{title}'=>$title,'{url}'=>CHtml::normalizeUrl($content['ajax']),'{id}'=>'#'.$tabId))."\n";
}
else
{
$tabsOut.=strtr($this->headerTemplate,array('{title}'=>$title,'{url}'=>'#'.$tabId,'{id}'=>$tabId))."\n";
if(isset($content['content']))
$contentOut.=strtr($this->contentTemplate,array('{content}'=>$content['content'],'{id}'=>$tabId))."\n";
}
}
echo "<ul>\n".$tabsOut."</ul>\n";
echo $contentOut;
echo CHtml::closeTag($this->tagName)."\n";
$options=CJavaScript::encode($this->options);
Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$id,"jQuery('#{$id}').tabs($options);");
}
/**
* Registers the core script files.
* This method overrides the parent implementation by registering the cookie plugin when cookie option is used.
*/
protected function registerCoreScripts()
{
parent::registerCoreScripts();
if(isset($this->options['cookie']))
Yii::app()->getClientScript()->registerCoreScript('cookie');
}
}

View File

@@ -0,0 +1,144 @@
<?php
/**
* CJuiWidget class file.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* This is the base class for all JUI widget classes.
*
* @author Sebastian Thierer <sebathi@gmail.com>
* @author Qiang Xue <qiang.xue@gmail.com>
* @package zii.widgets.jui
* @since 1.1
*/
abstract class CJuiWidget extends CWidget
{
/**
* @var string the root URL that contains all JUI JavaScript files.
* If this property is not set (default), Yii will publish the JUI package included in the zii release and use
* that to infer the root script URL. You should set this property if you intend to use
* a JUI package whose version is different from the one included in zii.
* Note that under this URL, there must be a file whose name is specified by {@link scriptFile}.
* Do not append any slash character to the URL.
*/
public $scriptUrl;
/**
* @var string the root URL that contains all JUI theme folders.
* If this property is not set (default), Yii will publish the JUI package included in the zii release and use
* that to infer the root theme URL. You should set this property if you intend to use
* a theme that is not found in the JUI package included in zii.
* Note that under this URL, there must be a directory whose name is specified by {@link theme}.
* Do not append any slash character to the URL.
*/
public $themeUrl;
/**
* @var string the JUI theme name. Defaults to 'base'. Make sure that under {@link themeUrl} there
* is a directory whose name is the same as this property value (case-sensitive).
*/
public $theme='base';
/**
* @var mixed the main JUI JavaScript file. Defaults to 'jquery-ui.min.js'.
* Note the file must exist under the URL specified by {@link scriptUrl}.
* If you need to include multiple script files (e.g. during development, you want to include individual
* plugin script files rather than the minized JUI script file), you may set this property
* as an array of the script file names.
* This property can also be set as false, which means the widget will not include any script file,
* and it is your responsibility to explicitly include it somewhere else.
*/
public $scriptFile='jquery-ui.min.js';
/**
* @var mixed the theme CSS file name. Defaults to 'jquery-ui.css'.
* Note the file must exist under the URL specified by {@link themeUrl}/{@link theme}.
* If you need to include multiple theme CSS files (e.g. during development, you want to include individual
* plugin CSS files), you may set this property as an array of the CSS file names.
* This property can also be set as false, which means the widget will not include any theme CSS file,
* and it is your responsibility to explicitly include it somewhere else.
*/
public $cssFile='jquery-ui.css';
/**
* @var array the initial JavaScript options that should be passed to the JUI plugin.
*/
public $options=array();
/**
* @var array the HTML attributes that should be rendered in the HTML tag representing the JUI widget.
*/
public $htmlOptions=array();
/**
* Initializes the widget.
* This method will publish JUI assets if necessary.
* It will also register jquery and JUI JavaScript files and the theme CSS file.
* If you override this method, make sure you call the parent implementation first.
*/
public function init()
{
$this->resolvePackagePath();
$this->registerCoreScripts();
parent::init();
}
/**
* Determine the JUI package installation path.
* This method will identify the JavaScript root URL and theme root URL.
* If they are not explicitly specified, it will publish the included JUI package
* and use that to resolve the needed paths.
*/
protected function resolvePackagePath()
{
if($this->scriptUrl===null || $this->themeUrl===null)
{
$cs=Yii::app()->getClientScript();
if($this->scriptUrl===null)
$this->scriptUrl=$cs->getCoreScriptUrl().'/jui/js';
if($this->themeUrl===null)
$this->themeUrl=$cs->getCoreScriptUrl().'/jui/css';
}
}
/**
* Registers the core script files.
* This method registers jquery and JUI JavaScript files and the theme CSS file.
*/
protected function registerCoreScripts()
{
$cs=Yii::app()->getClientScript();
if(is_string($this->cssFile))
$cs->registerCssFile($this->themeUrl.'/'.$this->theme.'/'.$this->cssFile);
elseif(is_array($this->cssFile))
{
foreach($this->cssFile as $cssFile)
$cs->registerCssFile($this->themeUrl.'/'.$this->theme.'/'.$cssFile);
}
$cs->registerCoreScript('jquery');
if(is_string($this->scriptFile))
$this->registerScriptFile($this->scriptFile);
elseif(is_array($this->scriptFile))
{
foreach($this->scriptFile as $scriptFile)
$this->registerScriptFile($scriptFile);
}
}
/**
* Registers a JavaScript file under {@link scriptUrl}.
* Note that by default, the script file will be rendered at the end of a page to improve page loading speed.
* @param string $fileName JavaScript file name
* @param integer $position the position of the JavaScript file. Valid values include the following:
* <ul>
* <li>CClientScript::POS_HEAD : the script is inserted in the head section right before the title element.</li>
* <li>CClientScript::POS_BEGIN : the script is inserted at the beginning of the body section.</li>
* <li>CClientScript::POS_END : the script is inserted at the end of the body section.</li>
* </ul>
*/
protected function registerScriptFile($fileName,$position=CClientScript::POS_END)
{
Yii::app()->getClientScript()->registerScriptFile($this->scriptUrl.'/'.$fileName,$position);
}
}