1
0
www.mikescher.com/framework/zii/widgets/CListView.php

326 lines
12 KiB
PHP
Raw Normal View History

2014-05-13 12:40:42 +02:00
<?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');
}
}