mirror of
https://github.com/YunoHost-Apps/limesurvey_ynh.git
synced 2024-09-03 19:36:32 +02:00
212 lines
No EOL
5.9 KiB
PHP
212 lines
No EOL
5.9 KiB
PHP
<?php
|
|
/**
|
|
* TbRelationalColumn class
|
|
*
|
|
* Displays a clickable column that will make an ajax request and display its resulting data
|
|
* into a new row.
|
|
*
|
|
* @author: antonio ramirez <antonio@clevertech.biz>
|
|
* Date: 9/25/12
|
|
* Time: 10:05 PM
|
|
*/
|
|
class TbRelationalColumn extends TbDataColumn
|
|
{
|
|
/**
|
|
* @var string $url the route to call via AJAX to get the data from
|
|
*/
|
|
public $url;
|
|
|
|
/**
|
|
* @var string $cssClass the class name that will wrap up the cell content.
|
|
* Important Note: this class will be used as the trigger for the AJAX call, so make sure is unique for the
|
|
* column.
|
|
*/
|
|
public $cssClass = 'tbrelational-column';
|
|
|
|
/**
|
|
* @var bool $cacheData if set to true, there won't be more than one AJAX request. If set to false, the widget will
|
|
* continuously make AJAX requests. This is useful if the data could vary. If the data doesn't change then is better
|
|
* to set it to true. Defaults to true.
|
|
*/
|
|
public $cacheData = true;
|
|
|
|
/**
|
|
* @var string a javascript function that will be invoked if an AJAX call occurs.
|
|
*
|
|
* The function signature is <code>function(tr, rowid, data)</code>
|
|
* <ul>
|
|
* <li><code>tr</code> is the newly created TR HTML object that will display the returned server data.</li>
|
|
* <li><code>rowid</code> the model id of the row.</li>
|
|
* <li><code>data</code> is the data returned by the server that is already displayed on the row.</li>
|
|
* </ul>
|
|
* Note: This handler is not called for JSONP requests.
|
|
*
|
|
* Example (add in a call to TbRelationalColumn):
|
|
* <pre>
|
|
* ...
|
|
* 'afterAjaxUpdate'=>'js:function(tr,rowid, data){ console.log(rowid); }',
|
|
* ...
|
|
* </pre>
|
|
*/
|
|
public $afterAjaxUpdate;
|
|
|
|
/**
|
|
* @var string $ajaxErrorMessage the message that is displayed on the newly created row in case there is an AJAX
|
|
* error.
|
|
*/
|
|
public $ajaxErrorMessage = 'Error';
|
|
|
|
/**
|
|
* widget initialization
|
|
*/
|
|
public function init()
|
|
{
|
|
parent::init();
|
|
|
|
if(empty($this->url))
|
|
{
|
|
$this->url = Yii::app()->getRequest()->requestUri;
|
|
}
|
|
|
|
$this->registerClientScript();
|
|
}
|
|
|
|
/**
|
|
* Overrides CDataColumn renderDataCell in order to wrap up its content with the object that will be used as a
|
|
* trigger.
|
|
* Important: Making use of links as a content for this of column is an error.
|
|
* @param int $row
|
|
*/
|
|
public function renderDataCell($row)
|
|
{
|
|
$data = $this->grid->dataProvider->data[$row];
|
|
$options = $this->htmlOptions;
|
|
if ($this->cssClassExpression !== null)
|
|
{
|
|
$class = $this->evaluateExpression($this->cssClassExpression, array('row' => $row, 'data' => $data));
|
|
if (isset($options['class']))
|
|
$options['class'] .= ' ' . $class;
|
|
else
|
|
$options['class'] = $class;
|
|
}
|
|
echo CHtml::openTag('td', $options);
|
|
echo CHtml::openTag('span', array('class' => $this->cssClass, 'data-rowid' => $this->getPrimaryKey($data)));
|
|
$this->renderDataCellContent($row, $data);
|
|
echo '</span>';
|
|
echo '</td>';
|
|
}
|
|
|
|
/**
|
|
* Helper function to return the primary key of the $data
|
|
* * IMPORTANT: composite keys on CActiveDataProviders will return the keys joined by comma
|
|
* @param $data
|
|
* @return null|string
|
|
*/
|
|
protected function getPrimaryKey($data)
|
|
{
|
|
if($this->grid->dataProvider instanceof CActiveDataProvider)
|
|
{
|
|
$key=$this->grid->dataProvider->keyAttribute===null ? $data->getPrimaryKey() : $data->{$this->keyAttribute};
|
|
return is_array($key) ? implode(',',$key) : $key;
|
|
}
|
|
if($this->grid->dataProvider instanceof CArrayDataProvider)
|
|
{
|
|
return is_object($data) ? $data->{$this->grid->dataProvider->keyField} : $data[$this->grid->dataProvider->keyField];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Register script that will handle its behavior
|
|
*/
|
|
public function registerClientScript()
|
|
{
|
|
Yii::app()->bootstrap->registerAssetCss('bootstrap-relational.css');
|
|
|
|
$cs = Yii::app()->getClientScript();
|
|
|
|
if($this->afterAjaxUpdate!==null)
|
|
{
|
|
if((!$this->afterAjaxUpdate instanceof CJavaScriptExpression) && strpos($this->afterAjaxUpdate,'js:')!==0)
|
|
{
|
|
$this->afterAjaxUpdate=new CJavaScriptExpression($this->afterAjaxUpdate);
|
|
}
|
|
else
|
|
{
|
|
$this->afterAjaxUpdate=$this->afterAjaxUpdate;
|
|
}
|
|
}
|
|
else
|
|
$this->afterAjaxUpdate = 'js:$.noop';
|
|
|
|
$this->ajaxErrorMessage = CHtml::encode($this->ajaxErrorMessage);
|
|
$afterAjaxUpdate = CJavaScript::encode($this->afterAjaxUpdate);
|
|
$span = count($this->grid->columns);
|
|
$loadingPic = CHtml::image(Yii::app()->bootstrap->getAssetsUrl().'/img/loading.gif');
|
|
$cache = $this->cacheData? 'true':'false';
|
|
$data = !empty($this->submitData) && is_array($this->submitData)? $this->submitData : 'js:{}';
|
|
$data = CJavascript::encode($data);
|
|
|
|
$js =<<<EOD
|
|
$(document).on('click','.{$this->cssClass}', function(){
|
|
var span = $span;
|
|
var that = $(this);
|
|
var status = that.data('status');
|
|
var rowid = that.data('rowid');
|
|
var tr = $('#relatedinfo'+rowid);
|
|
var parent = that.parents('tr');
|
|
var afterAjaxUpdate = {$afterAjaxUpdate};
|
|
|
|
if(status && status=='on'){return}
|
|
that.data('status','on');
|
|
|
|
if(tr.length && !tr.is(':visible') && {$cache})
|
|
{
|
|
tr.slideDown();
|
|
that.data('status','off');
|
|
return;
|
|
}else if(tr.length && tr.is(':visible'))
|
|
{
|
|
tr.slideUp();
|
|
that.data('status','off');
|
|
return;
|
|
}
|
|
if(tr.length)
|
|
{
|
|
tr.find('td').html('{$loadingPic}');
|
|
if(!tr.is(':visible')){
|
|
tr.slideDown();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var td = $('<td/>').html('{$loadingPic}').attr({'colspan':$span});
|
|
tr = $('<tr/>').prop({'id':'relatedinfo'+rowid}).append(td);
|
|
/* we need to maintain zebra styles :) */
|
|
var fake = $('<tr class="hide"/>').append($('<td/>').attr({'colspan':$span}));
|
|
parent.after(tr);
|
|
tr.after(fake);
|
|
}
|
|
var data = $.extend({$data}, {id:rowid});
|
|
$.ajax({
|
|
url: '{$this->url}',
|
|
data: data,
|
|
success: function(data){
|
|
tr.find('td').html(data);
|
|
that.data('status','off');
|
|
if($.isFunction(afterAjaxUpdate))
|
|
{
|
|
afterAjaxUpdate(tr,rowid,data);
|
|
}
|
|
},
|
|
error: function()
|
|
{
|
|
tr.find('td').html('{$this->ajaxErrorMessage}');
|
|
that.data('status','off');
|
|
}
|
|
});
|
|
});
|
|
EOD;
|
|
$cs->registerScript(__CLASS__.'#'.$this->id, $js);
|
|
}
|
|
} |