/
EditableColumn.php
116 lines (99 loc) · 3.76 KB
/
EditableColumn.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?php
/**
* EditableColumn class file.
*
* This widget makes editable column in GridView
*
* @author Vitaliy Potapov <noginsk@rambler.ru>
* @link https://github.com/vitalets/yii-bootstrap-editable
* @copyright Copyright © Vitaliy Potapov 2012
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
* @version 1.0.0
*/
Yii::import('ext.editable.EditableField');
Yii::import('zii.widgets.grid.CDataColumn');
class EditableColumn extends CDataColumn
{
//editable params
public $editable = array();
//flag to render client script only once
protected $isScriptRendered = false;
public function init()
{
if (!$this->grid->dataProvider instanceOf CActiveDataProvider) {
throw new CException('EditableColumn can be applied only to grid based on CActiveDataProvider');
}
if (!$this->name) {
throw new CException('You should provide name for EditableColumn');
}
parent::init();
if($this->isEditable($this->grid->dataProvider->model)) {
$this->attachAjaxUpdateEvent();
}
}
protected function renderDataCellContent($row, $data)
{
if(!$this->isEditable($data)) {
parent::renderDataCellContent($row, $data);
return;
}
$options = CMap::mergeArray($this->editable, array(
'model' => $data,
'attribute' => $this->name,
));
//if value defined for column --> use it as element text
if(strlen($this->value)) {
ob_start();
parent::renderDataCellContent($row, $data);
$text = ob_get_clean();
$options['text'] = $text;
$options['encode'] = false;
}
$editable = $this->grid->controller->createWidget('EditableField', $options);
//manually make selector non unique to match all cells in column
$selector = get_class($editable->model) . '_' . $editable->attribute;
$editable->htmlOptions['rel'] = $selector;
$editable->renderLink();
//manually render client script (one for all cells in column)
if (!$this->isScriptRendered) {
$script = $editable->registerClientScript();
Yii::app()->getClientScript()->registerScript(__CLASS__ . '#' . $selector.'-event', '
$("#'.$this->grid->id.'").parent().on("ajaxUpdate.yiiGridView", "#'.$this->grid->id.'", function() {'.$script.'});
');
$this->isScriptRendered = true;
}
}
/**
* Unfortunatly Yii yet does not support custom js events in it's widgets.
* So we need to invoke it manually to ensure update of editables on grid ajax update.
*
* issue in Yii github: https://github.com/yiisoft/yii/issues/1313
*
*/
protected function attachAjaxUpdateEvent()
{
$trigger = '$("#"+id).trigger("ajaxUpdate");';
//check if trigger already inserted by another column
if(strpos($this->grid->afterAjaxUpdate, $trigger) !== false) return;
//inserting trigger
if(strlen($this->grid->afterAjaxUpdate)) {
$orig = $this->grid->afterAjaxUpdate;
if(strpos($orig, 'js:')===0) $orig = substr($orig,3);
$orig = "\n($orig).apply(this, arguments);";
} else {
$orig = '';
}
$this->grid->afterAjaxUpdate = "js: function(id, data) {
$trigger $orig
}";
}
/**
* determines wether column currently editable or not
*
* @param mixed $model
*/
protected function isEditable($model)
{
return $model->isAttributeSafe($this->name) && (!array_key_exists('enabled', $this->editable) || $this->editable['enabled'] === true);
}
}