CButtonColumn.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. <?php
  2. /**
  3. * CButtonColumn class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. Yii::import('zii.widgets.grid.CGridColumn');
  11. /**
  12. * CButtonColumn represents a grid view column that renders one or several buttons.
  13. *
  14. * By default, it will display three buttons, "view", "update" and "delete", which triggers the corresponding
  15. * actions on the model of the row.
  16. *
  17. * By configuring {@link buttons} and {@link template} properties, the column can display other buttons
  18. * and customize the display order of the buttons.
  19. *
  20. * @author Qiang Xue <qiang.xue@gmail.com>
  21. * @package zii.widgets.grid
  22. * @since 1.1
  23. */
  24. class CButtonColumn extends CGridColumn
  25. {
  26. /**
  27. * @var array the HTML options for the data cell tags.
  28. */
  29. public $htmlOptions=array('class'=>'button-column');
  30. /**
  31. * @var array the HTML options for the header cell tag.
  32. */
  33. public $headerHtmlOptions=array('class'=>'button-column');
  34. /**
  35. * @var array the HTML options for the footer cell tag.
  36. */
  37. public $footerHtmlOptions=array('class'=>'button-column');
  38. /**
  39. * @var string the template that is used to render the content in each data cell.
  40. * These default tokens are recognized: {view}, {update} and {delete}. If the {@link buttons} property
  41. * defines additional buttons, their IDs are also recognized here. For example, if a button named 'preview'
  42. * is declared in {@link buttons}, we can use the token '{preview}' here to specify where to display the button.
  43. */
  44. public $template='{view} {update} {delete}';
  45. /**
  46. * @var string the label for the view button. Defaults to "View".
  47. * Note that the label will not be HTML-encoded when rendering.
  48. */
  49. public $viewButtonLabel;
  50. /**
  51. * @var string the image URL for the view button. If not set, an integrated image will be used.
  52. * You may set this property to be false to render a text link instead.
  53. */
  54. public $viewButtonImageUrl;
  55. /**
  56. * @var string a PHP expression that is evaluated for every view button and whose result is used
  57. * as the URL for the view button. In this expression, you can use the following variables:
  58. * <ul>
  59. * <li><code>$row</code> the row number (zero-based)</li>
  60. * <li><code>$data</code> the data model for the row</li>
  61. * <li><code>$this</code> the column object</li>
  62. * </ul>
  63. * The PHP expression will be evaluated using {@link evaluateExpression}.
  64. *
  65. * A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
  66. * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
  67. */
  68. public $viewButtonUrl='Yii::app()->controller->createUrl("view",array("id"=>$data->primaryKey))';
  69. /**
  70. * @var array the HTML options for the view button tag.
  71. */
  72. public $viewButtonOptions=array('class'=>'view');
  73. /**
  74. * @var string the label for the update button. Defaults to "Update".
  75. * Note that the label will not be HTML-encoded when rendering.
  76. */
  77. public $updateButtonLabel;
  78. /**
  79. * @var string the image URL for the update button. If not set, an integrated image will be used.
  80. * You may set this property to be false to render a text link instead.
  81. */
  82. public $updateButtonImageUrl;
  83. /**
  84. * @var string a PHP expression that is evaluated for every update button and whose result is used
  85. * as the URL for the update button. In this expression, you can use the following variables:
  86. * <ul>
  87. * <li><code>$row</code> the row number (zero-based)</li>
  88. * <li><code>$data</code> the data model for the row</li>
  89. * <li><code>$this</code> the column object</li>
  90. * </ul>
  91. * The PHP expression will be evaluated using {@link evaluateExpression}.
  92. *
  93. * A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
  94. * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
  95. */
  96. public $updateButtonUrl='Yii::app()->controller->createUrl("update",array("id"=>$data->primaryKey))';
  97. /**
  98. * @var array the HTML options for the update button tag.
  99. */
  100. public $updateButtonOptions=array('class'=>'update');
  101. /**
  102. * @var string the label for the delete button. Defaults to "Delete".
  103. * Note that the label will not be HTML-encoded when rendering.
  104. */
  105. public $deleteButtonLabel;
  106. /**
  107. * @var string the image URL for the delete button. If not set, an integrated image will be used.
  108. * You may set this property to be false to render a text link instead.
  109. */
  110. public $deleteButtonImageUrl;
  111. /**
  112. * @var string a PHP expression that is evaluated for every delete button and whose result is used
  113. * as the URL for the delete button. In this expression, you can use the following variables:
  114. * <ul>
  115. * <li><code>$row</code> the row number (zero-based)</li>
  116. * <li><code>$data</code> the data model for the row</li>
  117. * <li><code>$this</code> the column object</li>
  118. * </ul>
  119. * The PHP expression will be evaluated using {@link evaluateExpression}.
  120. *
  121. * A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
  122. * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
  123. */
  124. public $deleteButtonUrl='Yii::app()->controller->createUrl("delete",array("id"=>$data->primaryKey))';
  125. /**
  126. * @var array the HTML options for the delete button tag.
  127. */
  128. public $deleteButtonOptions=array('class'=>'delete');
  129. /**
  130. * @var string the confirmation message to be displayed when delete button is clicked.
  131. * By setting this property to be false, no confirmation message will be displayed.
  132. * This property is used only if <code>$this->buttons['delete']['click']</code> is not set.
  133. */
  134. public $deleteConfirmation;
  135. /**
  136. * @var string a javascript function that will be invoked after the delete ajax call.
  137. * This property is used only if <code>$this->buttons['delete']['click']</code> is not set.
  138. *
  139. * The function signature is <code>function(link, success, data)</code>
  140. * <ul>
  141. * <li><code>link</code> references the delete link.</li>
  142. * <li><code>success</code> status of the ajax call, true if the ajax call was successful, false if the ajax call failed.
  143. * <li><code>data</code> the data returned by the server in case of a successful call or XHR object in case of error.
  144. * </ul>
  145. * Note that if success is true it does not mean that the delete was successful, it only means that the ajax call was successful.
  146. *
  147. * Example:
  148. * <pre>
  149. * array(
  150. * class'=>'CButtonColumn',
  151. * 'afterDelete'=>'function(link,success,data){ if(success) alert("Delete completed successfully"); }',
  152. * ),
  153. * </pre>
  154. */
  155. public $afterDelete;
  156. /**
  157. * @var array the configuration for buttons. Each array element specifies a single button
  158. * which has the following format:
  159. * <pre>
  160. * 'buttonID' => array(
  161. * 'label'=>'...', // text label of the button
  162. * 'url'=>'...', // a PHP expression for generating the URL of the button
  163. * 'imageUrl'=>'...', // image URL of the button. If not set or false, a text link is used
  164. * 'options'=>array(...), // HTML options for the button tag
  165. * 'click'=>'...', // a JS function to be invoked when the button is clicked
  166. * 'visible'=>'...', // a PHP expression for determining whether the button is visible
  167. * )
  168. * </pre>
  169. *
  170. * In the PHP expression for the 'url' option and/or 'visible' option, the variable <code>$row</code>
  171. * refers to the current row number (zero-based), and <code>$data</code> refers to the data model for
  172. * the row.
  173. * The PHP expression will be evaluated using {@link evaluateExpression}.
  174. * A PHP expression can be any PHP code that has a value. To learn more about what an expression is,
  175. * please refer to the {@link http://www.php.net/manual/en/language.expressions.php php manual}.
  176. *
  177. * If the 'buttonID' is 'view', 'update' or 'delete' the options will be applied to the default buttons.
  178. *
  179. * Note that in order to display non-default buttons, the {@link template} property needs to
  180. * be configured so that the corresponding button IDs appear as tokens in the template.
  181. */
  182. public $buttons=array();
  183. /**
  184. * Initializes the column.
  185. * This method registers necessary client script for the button column.
  186. */
  187. public function init()
  188. {
  189. $this->initDefaultButtons();
  190. foreach($this->buttons as $id=>$button)
  191. {
  192. if(strpos($this->template,'{'.$id.'}')===false)
  193. unset($this->buttons[$id]);
  194. elseif(isset($button['click']))
  195. {
  196. if(!isset($button['options']['class']))
  197. $this->buttons[$id]['options']['class']=$id;
  198. if(!($button['click'] instanceof CJavaScriptExpression))
  199. $this->buttons[$id]['click']=new CJavaScriptExpression($button['click']);
  200. }
  201. }
  202. $this->registerClientScript();
  203. }
  204. /**
  205. * Initializes the default buttons (view, update and delete).
  206. */
  207. protected function initDefaultButtons()
  208. {
  209. if($this->viewButtonLabel===null)
  210. $this->viewButtonLabel=Yii::t('zii','View');
  211. if($this->updateButtonLabel===null)
  212. $this->updateButtonLabel=Yii::t('zii','Update');
  213. if($this->deleteButtonLabel===null)
  214. $this->deleteButtonLabel=Yii::t('zii','Delete');
  215. if($this->viewButtonImageUrl===null)
  216. $this->viewButtonImageUrl=$this->grid->baseScriptUrl.'/view.png';
  217. if($this->updateButtonImageUrl===null)
  218. $this->updateButtonImageUrl=$this->grid->baseScriptUrl.'/update.png';
  219. if($this->deleteButtonImageUrl===null)
  220. $this->deleteButtonImageUrl=$this->grid->baseScriptUrl.'/delete.png';
  221. if($this->deleteConfirmation===null)
  222. $this->deleteConfirmation=Yii::t('zii','Are you sure you want to delete this item?');
  223. foreach(array('view','update','delete') as $id)
  224. {
  225. $button=array(
  226. 'label'=>$this->{$id.'ButtonLabel'},
  227. 'url'=>$this->{$id.'ButtonUrl'},
  228. 'imageUrl'=>$this->{$id.'ButtonImageUrl'},
  229. 'options'=>$this->{$id.'ButtonOptions'},
  230. );
  231. if(isset($this->buttons[$id]))
  232. $this->buttons[$id]=array_merge($button,$this->buttons[$id]);
  233. else
  234. $this->buttons[$id]=$button;
  235. }
  236. if(!isset($this->buttons['delete']['click']))
  237. {
  238. if(is_string($this->deleteConfirmation))
  239. $confirmation="if(!confirm(".CJavaScript::encode($this->deleteConfirmation).")) return false;";
  240. else
  241. $confirmation='';
  242. if(Yii::app()->request->enableCsrfValidation)
  243. {
  244. $csrfTokenName = Yii::app()->request->csrfTokenName;
  245. $csrfToken = Yii::app()->request->csrfToken;
  246. $csrf = "\n\t\tdata:{ '$csrfTokenName':'$csrfToken' },";
  247. }
  248. else
  249. $csrf = '';
  250. if($this->afterDelete===null)
  251. $this->afterDelete='function(){}';
  252. $this->buttons['delete']['click']=<<<EOD
  253. function() {
  254. $confirmation
  255. var th = this,
  256. afterDelete = $this->afterDelete;
  257. jQuery('#{$this->grid->id}').yiiGridView('update', {
  258. type: 'POST',
  259. url: jQuery(this).attr('href'),$csrf
  260. success: function(data) {
  261. jQuery('#{$this->grid->id}').yiiGridView('update');
  262. afterDelete(th, true, data);
  263. },
  264. error: function(XHR) {
  265. return afterDelete(th, false, XHR);
  266. }
  267. });
  268. return false;
  269. }
  270. EOD;
  271. }
  272. }
  273. /**
  274. * Registers the client scripts for the button column.
  275. */
  276. protected function registerClientScript()
  277. {
  278. $js=array();
  279. foreach($this->buttons as $id=>$button)
  280. {
  281. if(isset($button['click']))
  282. {
  283. $function=CJavaScript::encode($button['click']);
  284. $class=preg_replace('/\s+/','.',$button['options']['class']);
  285. $js[]="jQuery(document).on('click','#{$this->grid->id} a.{$class}',$function);";
  286. }
  287. }
  288. if($js!==array())
  289. Yii::app()->getClientScript()->registerScript(__CLASS__.'#'.$this->id, implode("\n",$js));
  290. }
  291. /**
  292. * Returns the data cell content.
  293. * This method renders the view, update and delete buttons in the data cell.
  294. * @param integer $row the row number (zero-based)
  295. * @return string the data cell content.
  296. * @since 1.1.16
  297. */
  298. public function getDataCellContent($row)
  299. {
  300. $data=$this->grid->dataProvider->data[$row];
  301. $tr=array();
  302. ob_start();
  303. foreach($this->buttons as $id=>$button)
  304. {
  305. $this->renderButton($id,$button,$row,$data);
  306. $tr['{'.$id.'}']=ob_get_contents();
  307. ob_clean();
  308. }
  309. ob_end_clean();
  310. return strtr($this->template,$tr);
  311. }
  312. /**
  313. * Renders a link button.
  314. * @param string $id the ID of the button
  315. * @param array $button the button configuration which may contain 'label', 'url', 'imageUrl' and 'options' elements.
  316. * See {@link buttons} for more details.
  317. * @param integer $row the row number (zero-based)
  318. * @param mixed $data the data object associated with the row
  319. */
  320. protected function renderButton($id,$button,$row,$data)
  321. {
  322. if (isset($button['visible']) && !$this->evaluateExpression($button['visible'],array('row'=>$row,'data'=>$data)))
  323. return;
  324. $label=isset($button['label']) ? $button['label'] : $id;
  325. $url=isset($button['url']) ? $this->evaluateExpression($button['url'],array('data'=>$data,'row'=>$row)) : '#';
  326. $options=isset($button['options']) ? $button['options'] : array();
  327. if(!isset($options['title']))
  328. $options['title']=$label;
  329. if(isset($button['imageUrl']) && is_string($button['imageUrl']))
  330. echo CHtml::link(CHtml::image($button['imageUrl'],$label),$url,$options);
  331. else
  332. echo CHtml::link($label,$url,$options);
  333. }
  334. }