*/ Yii::import('zii.widgets.grid.CGridView'); Yii::import('zii.widgets.grid.CCheckBoxColumn'); /** * SelGridView v1.1 * * SelGridView remembers selected rows of gridview when sorting or navigating by pages. Also it can select particular rows by GET param when page is loading * * Usage: * Just put this file to extensions directory, create widget as usual and enjoy * *
* $this->widget('application.extensions.SelGridView', array(
* ...
* ));
* 
*/ class SelCheckboxColumn extends CCheckBoxColumn { public function renderFilterCell() { // } } class SelGridView extends CGridView { /** * GET param name to pass selected row(s) * * @var mixed */ public $selVar; /** * Creates column objects and initializes them. * Automatically add hidden checkbox column. */ protected function initColumns() { parent::initColumns(); if($this->selectableRows == 0) return; if(empty($this->selVar)) { $this->selVar = $this->dataProvider->getId().'_sel'; } //if gridview already has user defined Checkbox column --> exit foreach($this->columns as $col) { if($col instanceof CCheckBoxColumn) return; } if($this->dataProvider instanceOf CActiveDataProvider) { $primaryKey = '$data->primaryKey'; } elseif($this->dataProvider instanceOf CArrayDataProvider) { $primaryKey = '$data["'.$this->dataProvider->keyField.'"]'; } else { throw new CException('Unsupported DataProvider!'); } //creating hidden checkbox column $checkboxColumn = new SelCheckboxColumn($this); $checkboxColumn->checked = 'isset($_GET["'.$this->selVar.'"]) ? in_array('.$primaryKey.', is_array($_GET["'.$this->selVar.'"]) ? $_GET["'.$this->selVar.'"] : array($_GET["'.$this->selVar.'"])) : false;'; $checkboxColumn->htmlOptions = array('style'=>'display:none'); $checkboxColumn->headerHtmlOptions = array('style'=>'display:none'); $checkboxColumn->footerHtmlOptions = array('style'=>'display:none'); $checkboxColumn->init(); $this->columns[] = $checkboxColumn; } /** * Registers necessary client scripts. * Automaticlly prepend user's beforeajaxUpdate with needed code that will modify GET params when navigating and sorting */ public function registerClientScript() { if($this->selectableRows > 0) $this->applyBeforeAjaxUpdate(); parent::registerClientScript(); } /** * prepending user's beforeajaxUpdate with needed code * */ protected function applyBeforeAjaxUpdate() { $funcChangeQuery = ' function(id, options) { if(this.selectableRows == 0) return; //all GET params in current url var params = $.deparam.querystring(options.url); //GET param named "{ModelClass}_sel" showing selected rows in whole grid (not only current page) var selVar = "'.$this->selVar.'"; var checkedInQuery = (params[selVar]) ? params[selVar] : []; if(!$.isArray(checkedInQuery)) checkedInQuery = [checkedInQuery]; //rows selected on current page var checkedInPage = $.fn.yiiGridView.getSelection(id); //if only one row can be selected - logic is simple: if any row selected on current page, clear all previously selected if(this.selectableRows == 1) { if(!checkedInPage.length) return; params[selVar] = checkedInPage; options.url = $.param.querystring(options.url, params); return; } //iterating all keys of this page $("#"+id).find(".keys span").each(function (i) { var key = $(this).text(); //row found in GET params var indexInQuery = $.inArray(key, checkedInQuery); //row is checked on current page var indexInChecked = $.inArray(key, checkedInPage); //row is selected and not in GET params --> adding to GET params if(indexInChecked >= 0 && indexInQuery == -1) { checkedInQuery.push(key); } //row not selected, but in GET params due to selected previously --> deleting from GET params if(indexInChecked == -1 && indexInQuery >= 0) { delete checkedInQuery[indexInQuery]; } }); if(!checkedInQuery) { if(params[selVar]) delete params[selVar]; } else { params[selVar] = checkedInQuery; } options.url = $.param.querystring( options.url, params); } '; if(empty($this->beforeAjaxUpdate)) { //no user defined ajaxUpdate handler. Simply use SelGridView's $this->beforeAjaxUpdate = $funcChangeQuery; } else { //beforeAjaxUpdate = function or direct JS code if(preg_match('/(function.+\})/is', $this->beforeAjaxUpdate, $matches)) { $userScript = '('.$matches[0].')(id, options);'; } else { $userScript = $this->beforeAjaxUpdate; } //merge to one beforeAjaxUpdate function $this->beforeAjaxUpdate = ' function(id, options) { ('.$funcChangeQuery.')(id, options); '.$userScript.' } '; } } }