1 <?php
2 3 4 5 6 7 8 9 10 11 12 13
14 Yii::import('bootstrap.widgets.TbDataColumn');
15
16 class WhRelationalColumn extends TbDataColumn
17 {
18 19 20
21 public $url;
22
23 24 25 26 27
28 public $cssClass = 'wh-relational-column';
29
30 31 32 33 34
35 public $cacheData = true;
36
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
55 public $afterAjaxUpdate;
56
57 58 59 60
61 public $ajaxErrorMessage = 'Error';
62
63 64 65
66 public function init()
67 {
68 parent::init();
69
70 if (empty($this->url))
71 $this->url = Yii::app()->getRequest()->requestUri;
72
73 $this->attachBehavior('ywplugin', array('class' => 'yiiwheels.behaviors.WhPlugin'));
74 $this->registerClientScript();
75 }
76
77 78 79 80 81 82
83 public function renderDataCell($row)
84 {
85 $data = $this->grid->dataProvider->data[$row];
86 $options = $this->htmlOptions;
87 if ($this->cssClassExpression !== null) {
88 $class = $this->evaluateExpression($this->cssClassExpression, array('row' => $row, 'data' => $data));
89 if (isset($options['class']))
90 $options['class'] .= ' ' . $class;
91 else
92 $options['class'] = $class;
93 }
94 echo CHtml::openTag('td', $options);
95 echo CHtml::openTag('span', array('class' => $this->cssClass, 'data-rowid' => $this->getPrimaryKey($data)));
96 $this->renderDataCellContent($row, $data);
97 echo '</span>';
98 echo '</td>';
99 }
100
101 102 103 104 105 106
107 protected function getPrimaryKey($data)
108 {
109 if ($this->grid->dataProvider instanceof CActiveDataProvider) {
110 $key = $this->grid->dataProvider->keyAttribute === null ? $data->getPrimaryKey(
111 ) : $data->{$this->keyAttribute};
112 return is_array($key) ? implode(',', $key) : $key;
113 }
114 if ($this->grid->dataProvider instanceof CArrayDataProvider || $this->grid->dataProvider instanceof CSqlDataProvider)
115 return is_object(
116 $data
117 ) ? $data->{$this->grid->dataProvider->keyField} : $data[$this->grid->dataProvider->keyField];
118
119 return null;
120 }
121
122 123 124
125 public function registerClientScript()
126 {
127 $path = __DIR__ . DIRECTORY_SEPARATOR . 'assets';
128 $assetsUrl = $this->getAssetsUrl($path);
129
130
131 $cs = Yii::app()->getClientScript();
132 $cs->registerCssFile($assetsUrl . '/css/bootstrap-relational.css');
133
134 if ($this->afterAjaxUpdate !== null) {
135 if ((!$this->afterAjaxUpdate instanceof CJavaScriptExpression) && strpos(
136 $this->afterAjaxUpdate,
137 'js:'
138 ) !== 0
139 )
140 $this->afterAjaxUpdate = new CJavaScriptExpression($this->afterAjaxUpdate);
141 } else
142 $this->afterAjaxUpdate = 'js:$.noop';
143
144 $this->ajaxErrorMessage = CHtml::encode($this->ajaxErrorMessage);
145 $afterAjaxUpdate = CJavaScript::encode($this->afterAjaxUpdate);
146 $span = count($this->grid->columns);
147 $loadingPic = CHtml::image(Yii::app()->yiiwheels->getAssetsUrl() . '/img/loading.gif');
148 $cache = $this->cacheData ? 'true' : 'false';
149 $data = !empty($this->submitData) && is_array(
150 $this->submitData
151 ) ? $this->submitData : 'js:{}';
152 $data = CJavascript::encode($data);
153
154 $js = <<<EOD
155 $(document).on('click','.{$this->cssClass}', function(){
156 var span = $span;
157 var that = $(this);
158 var status = that.data('status');
159 var rowid = that.data('rowid');
160 var tr = $('#relatedinfo'+rowid);
161 var parent = that.parents('tr').eq(0);
162 var afterAjaxUpdate = {$afterAjaxUpdate};
163
164 if (status && status=='on'){return}
165 that.data('status','on');
166
167 if (tr.length && !tr.is(':visible') && {$cache})
168 {
169 tr.slideDown();
170 that.data('status','off');
171 return;
172 }else if (tr.length && tr.is(':visible'))
173 {
174 tr.slideUp();
175 that.data('status','off');
176 return;
177 }
178 if (tr.length)
179 {
180 tr.find('td').html('{$loadingPic}');
181 if (!tr.is(':visible')){
182 tr.slideDown();
183 }
184 }
185 else
186 {
187 var td = $('<td/>').html('{$loadingPic}').attr({'colspan':$span});
188 tr = $('<tr/>').prop({'id':'relatedinfo'+rowid}).append(td);
189 /* we need to maintain zebra styles :) */
190 var fake = $('<tr class="hide"/>').append($('<td/>').attr({'colspan':$span}));
191 parent.after(tr);
192 tr.after(fake);
193 }
194 var data = $.extend({$data}, {id:rowid});
195 $.ajax({
196 url: '{$this->url}',
197 data: data,
198 success: function(data){
199 tr.find('td').html(data);
200 that.data('status','off');
201 if ($.isFunction(afterAjaxUpdate))
202 {
203 afterAjaxUpdate(tr,rowid,data);
204 }
205 },
206 error: function()
207 {
208 tr.find('td').html('{$this->ajaxErrorMessage}');
209 that.data('status','off');
210 }
211 });
212 });
213 EOD;
214 $cs->registerScript(__CLASS__ . '#' . $this->id, $js);
215 }
216 }
217