PageRenderTime 42ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/atk4/lib/Grid/Advanced.php

https://github.com/intuititve/lostandfound
PHP | 716 lines | 551 code | 29 blank | 136 comment | 52 complexity | 0ebe4517da825c82072f887123284d2c MD5 | raw file
Possible License(s): AGPL-3.0
  1. <?php // vim:ts=4:sw=4:et:fdm=marker
  2. /**
  3. * This is a Basic Grid implementation, which produces fully
  4. * functional HTML grid capable of filtering, sorting, paginating
  5. * and using multiple column formatters.
  6. *
  7. * @link http://agiletoolkit.org/doc/grid
  8. *
  9. * Use:
  10. * $grid=$this->add('Grid');
  11. * $grid->setModel('User');
  12. *
  13. * @license See http://agiletoolkit.org/about/license
  14. *
  15. **/
  16. class Grid_Advanced extends Grid_Basic {
  17. protected $no_records_message="No matching records to display";
  18. public $last_column;
  19. public $sortby='0';
  20. public $sortby_db=null;
  21. public $not_found=false;
  22. public $displayed_rows=0;
  23. private $totals_title_field=null;
  24. private $totals_title="";
  25. public $totals_t=null;
  26. public $totals_value_na = '-';
  27. public $data=null;
  28. /**
  29. * Inline related property
  30. * If true - TAB key submits row and activates next row
  31. */
  32. protected $tab_moves_down=false;
  33. /**
  34. * Inline related property
  35. * Wether or not to show submit line
  36. */
  37. protected $show_submit=true;
  38. private $record_order=null;
  39. public $title_col=array();
  40. /**
  41. * $tdparam property is an array with cell parameters specified in td tag.
  42. * This should be a hash: 'param_name'=>'param_value'
  43. * Following parameters treated and processed in a special way:
  44. * 1) 'style': nested array, style parameter. items of this nested array converted to a form of
  45. * style: style="param_name: param_value; param_name: param_value"
  46. * 2) OBSOLTE! wrap: possible values are true|false; if true, 'wrap' is added
  47. * use style/white-space property or simply format_wrap()
  48. *
  49. * All the rest are not checked and converted to a form of param_name="param_value"
  50. *
  51. * This is a tree-like array with the following structure:
  52. * array(
  53. * [level1]=>dataset_row=array(
  54. * [level2]=>field=array(
  55. * [level3]=>tdparam_elements=array(
  56. * param_name=>param_value
  57. * )
  58. * )
  59. * )
  60. * )
  61. */
  62. protected $tdparam=array();
  63. public $js_widget='ui.atk4_grid';
  64. public $js_widget_arguments=array();
  65. public $default_controller='MVCGrid';
  66. function init(){
  67. parent::init();
  68. //$this->add('Reloadable');
  69. //$this->api->addHook('pre-render',array($this,'precacheTemplate'));
  70. $this->sortby=$this->learn('sortby',@$_GET[$this->name.'_sort']);
  71. }
  72. function importFields($model,$fields=undefined){
  73. $this->add('Controller_MVCGrid')->importFields($model,$fields);
  74. }
  75. function defaultTemplate(){
  76. return array('grid');
  77. }
  78. /**
  79. * Returns the ID value of the expanded content on the basis of GET parameters
  80. */
  81. function getExpanderId(){
  82. return $_GET['expanded'].'_expandedcontent_'.$_GET['id'];
  83. }
  84. function getColumn($column){
  85. $this->last_column=$column;
  86. return $this;
  87. }
  88. function hasColumn($column){
  89. if(!is_string($column))throw $this->exception('WRong');
  90. return isset($this->columns[$column]);
  91. }
  92. function removeColumn($name){
  93. unset($this->columns[$name]);
  94. if($this->last_column==$name)$this->last_column=null;
  95. return $this;
  96. }
  97. function addButton($label,$name=null,$return_button=false){
  98. $button=$this->add('Button','gbtn'.count($this->elements),'grid_buttons');
  99. $button->setLabel($label);
  100. if($return_button)return $button;
  101. return $button;
  102. }
  103. function addQuickSearch($fields,$class='QuickSearch'){
  104. return $this->add($class,null,'quick_search')
  105. ->useWith($this)
  106. ->useFields($fields);
  107. }
  108. function makeSortable($db_sort=null){
  109. // Sorting
  110. $reverse=false;
  111. if(substr($db_sort,0,1)=='-'){
  112. $reverse=true;
  113. $db_sort=substr($db_sort,1);
  114. }
  115. if(!$db_sort)$db_sort=$this->last_column;
  116. if($this->sortby==$this->last_column){
  117. // we are already sorting by this column
  118. $info=array('1',$reverse?0:("-".$this->last_column));
  119. $this->sortby_db=$db_sort;
  120. }elseif($this->sortby=="-".$this->last_column){
  121. // We are sorted reverse by this column
  122. $info=array('2',$reverse?$this->last_column:'0');
  123. $this->sortby_db="-".$db_sort;
  124. }else{
  125. // we are not sorted by this column
  126. $info=array('0',$reverse?("-".$this->last_column):$this->last_column);
  127. }
  128. $this->columns[$this->last_column]['sortable']=$info;
  129. return $this;
  130. }
  131. function makeTitle(){
  132. $this->title_col[]=$this->last_column;
  133. return $this;
  134. }
  135. function render(){
  136. if($this->js_widget){
  137. $fn=str_replace('ui.','',$this->js_widget);
  138. $this->js(true)->_load($this->js_widget)->$fn($this->js_widget_arguments);
  139. }
  140. return parent::render();
  141. }
  142. function format_number($field){
  143. }
  144. function format_text($field){
  145. $this->current_row[$field] = $this->current_row[$field];
  146. }
  147. function format_html($field){
  148. $this->current_row_html[$field] = $this->current_row[$field];
  149. }
  150. function init_money($field){
  151. @$this->columns[$field]['thparam'].=' style="text-align: right"';
  152. }
  153. function init_real($field){
  154. @$this->columns[$field]['thparam'].=' style="text-align: right"';
  155. }
  156. function init_fullwidth($field){
  157. @$this->columns[$field]['thparam'].=' style="width: 100%"';
  158. }
  159. function format_fullwidth($field){}
  160. function format_money($field){
  161. $m=(float)$this->current_row[$field];
  162. $this->current_row[$field]=number_format($m,2);
  163. if($m<0){
  164. $this->setTDParam($field,'style/color','red');
  165. }else{
  166. $this->setTDParam($field,'style/color',null);
  167. }
  168. $this->setTDParam($field,'align','right');
  169. }
  170. function format_totals_number($field){
  171. return $this->format_number($field);
  172. }
  173. function format_totals_money($field){
  174. return $this->format_money($field);
  175. }
  176. function format_totals_real($field){
  177. return $this->format_real($field);
  178. }
  179. function format_totals_text($field){
  180. // This method is mainly for totals title displaying
  181. if($field==$this->totals_title_field){
  182. $this->setTDParam($field,'style/font-weight','bold');
  183. //$this->current_row[$field]=$this->totals_title.':';
  184. }
  185. else $this->current_row[$field]=$this->totals_value_na;
  186. }
  187. function format_time($field){
  188. $this->current_row[$field]=date($this->api->getConfig('locale/time','H:i:s'),
  189. strtotime($this->current_row[$field]));
  190. }
  191. function format_date($field){
  192. if(!$this->current_row[$field])$this->current_row[$field]='-'; else
  193. $this->current_row[$field]=date($this->api->getConfig('locale/date','d/m/Y'),
  194. strtotime($this->current_row[$field]));
  195. }
  196. function format_datetime($field){
  197. if(!$this->current_row[$field])$this->current_row[$field]='-'; else
  198. $this->current_row[$field]=date($this->api->getConfig('locale/datetime','d/m/Y H:i:s'),
  199. strtotime($this->current_row[$field]));
  200. }
  201. function format_timestamp($field){
  202. if(!$this->current_row[$field])$this->current_row[$field]='-';
  203. else{
  204. $format=$this->api->getConfig('locale/timestamp',$this->api->getConfig('locale/datetime','d/m/Y H:i:s'));
  205. $this->current_row[$field]=date($format,strtotime($this->current_row[$field]));
  206. }
  207. }
  208. function format_nowrap($field){
  209. $this->tdparam[$this->getCurrentIndex()][$field]['style']='nwhite-space: nowrap';
  210. }
  211. function format_wrap($field){
  212. $this->tdparam[$this->getCurrentIndex()][$field]['style']='white-space: wrap';
  213. }
  214. function format_template($field){
  215. if(!($t=$this->columns[$field]['template'])){
  216. throw new BaseException('use setTemplate() for field '.$field);
  217. }
  218. $this->current_row_html[$field]=$t
  219. ->set($this->current_row)
  220. ->trySet('_value_',$this->current_row[$field])
  221. ->render();
  222. }
  223. function format_widget($field, $widget, $params=array(), $widget_json=null){
  224. $class=$this->name.'_'.$field.'_expander';
  225. $params=array(
  226. 'class'=>$class."_".$field." $widget lister_cell"
  227. )+$params;
  228. $this->js(true)->_tag('.'.$class.'_'.$field)->_load($widget)->activate($widget_json);
  229. /*
  230. $this->api->add('jUI')->addWidget($widget)->activate('.'.$class.'_'.$field,$widget_json);
  231. */
  232. $this->tdparam[$this->getCurrentIndex()][$field]=$params;
  233. if(!$this->current_row[$field]){
  234. $this->current_row[$field]=$this->columns[$field]['descr'];
  235. }
  236. }
  237. function format_expander_widget($field,$column){
  238. return $this->format_expander($field,$column);
  239. }
  240. function format_expander($field, $column){
  241. $class=$this->name.'_'.$field.'_expander';
  242. if(!@$this->current_row[$field]){
  243. $this->current_row[$field]=$column['descr'];
  244. }
  245. // TODO:
  246. // reformat this using Button, once we have more advanced system to bypass rendering of
  247. // sub-elements.
  248. // $this->current_row[$field]=$this->add('Button',null,false)
  249. // ->
  250. //
  251. @$this->current_row_html[$field]='<input type="checkbox" class="button_'.$field.' '.$class.'"
  252. id="'.$this->name.'_'.$field.'_'.$this->current_row[$column['idfield']?$column['idfield']:'id'].'"
  253. rel="'.$this->api->getDestinationURL($column['page']?$column['page']:'./'.$field,
  254. array('expander'=>$field,
  255. 'cut_page'=>1,
  256. 'expanded'=>$this->name,
  257. // TODO: id is obsolete
  258. 'id'=>$this->current_row[$column['idfield']?$column['idfield']:'id'],
  259. $this->columns[$field]['refid'].'_id'=>$this->current_row[$column['idfield']?$column['idfield']:'id']
  260. )
  261. ).'"
  262. /><label for="'.$this->name.'_'.$field.'_'.$this->current_row[$column['idfield']?$column['idfield']:'id'].'">'.
  263. $this->current_row[$field].'</label>';
  264. }
  265. function init_expander_widget($field){
  266. @$this->columns[$field]['thparam'].=' style="width: 40px; text-align: center"';
  267. return $this->init_expander($field);
  268. }
  269. function init_expander($field){
  270. @$this->columns[$field]['thparam'].=' style="width: 40px; text-align: center"';
  271. $this->js(true)->find('.button_'.$field)->button();
  272. if(!isset($this->columns[$field]['refid'])){
  273. // TODO: test
  274. /*
  275. $refid=$this->getController();
  276. if($refid)$refid=$refid->getModel();
  277. */
  278. $refid=$this->model;
  279. //if($refid)$refid=$refid->entity_code;
  280. if($refid)$refid=$refid->getEntityCode();//Get Protected property Model::entity_code
  281. if($refid){
  282. $this->columns[$field]['refid']=$refid;
  283. }else{
  284. if($this->dq)
  285. $refid=$this->dq->args['table'];
  286. if(!$refid)$refid=preg_replace('/.*_/','',$this->api->page);
  287. $this->columns[$field]['refid']=$refid;
  288. }
  289. }
  290. $class=$this->name.'_'.$field.'_expander';
  291. $this->js(true)->_selector('.'.$class)->_load('ui.atk4_expander')->atk4_expander();
  292. }
  293. function _getFieldType($field){
  294. return 'line';
  295. }
  296. function _inlineUpdate($field,$id,$value){
  297. $this->dq->set($field,$value)->where($this->dq->args['table'].'.id',$id)->do_update();
  298. }
  299. function format_inline($field, $idfield='id'){
  300. /**
  301. * Formats the InlineEdit: field that on click should substitute the text
  302. * in the columns of the row by the edit controls
  303. *
  304. * The point is to set an Id for each column of the row. To do this, we should
  305. * set a property showing that id should be added in prerender
  306. */
  307. $val=$this->current_row[$field];
  308. $this->current_row_html[$field]='<span id="'.($s=$this->name.'_'.$field.'_inline_'.
  309. $this->current_id).'" >'.
  310. '<i style="float: left" class="atk-icon atk-icons-red atk-icon-office-pencil"></i>'.
  311. $this->current_row[$field].
  312. '</span>';
  313. $this->js(true)->_selector('#'.$s)->click(
  314. $this->js()->_enclose()->_selectorThis()->parent()->atk4_load($this->api->getDestinationURL(null,array($s=>true)))
  315. );
  316. if($_GET[$s]){
  317. // clicked on link
  318. $this->api->stickyGET($s);
  319. $f=$this->owner->add('Form',$s,null,array('form_empty','form'));
  320. $ff=$f->addField($this->_getFieldType($field),'e','');
  321. $ff->set($val);
  322. $ff->js('blur',$this->js()->atk4_grid('reloadRow',$this->current_id));
  323. $ff->js(true)->css(array('width'=>'100%'));
  324. $_GET['cut_object']=$f->name;
  325. if($f->isSubmitted()){
  326. $this->_inlineUpdate($field,$this->current_id,$f->get('e'));
  327. $this->js()->atk4_grid('reloadRow',$this->current_id)->execute();
  328. }
  329. $f->recursiveRender();
  330. }
  331. }
  332. function format_nl2br($field) {
  333. $this->current_row[$field] = nl2br($this->current_row[$field]);
  334. }
  335. function format_order($field, $idfield='id'){
  336. $n=$this->name.'_'.$field.'_'.$this->current_row[$idfield];
  337. $this->tdparam[$this->getCurrentIndex()][$field]=array(
  338. 'id'=>$n,
  339. 'style'=>array(
  340. 'cursor'=>'hand'
  341. )
  342. );
  343. $this->current_row[$field]=$this->record_order->getCell($this->current_id);
  344. }
  345. function init_link($field){
  346. $this->setTemplate('<a href="<?'.'$_link?'.'>"><?'.'$'.$field.'?'.'></a>');
  347. }
  348. function format_link($field){
  349. $this->current_row['_link']=$this->api->getDestinationURL('./details',array('id'=>$this->current_id));
  350. return $this->format_template($field);
  351. /*
  352. $this->current_row[$field]='<a href="'.$this->api->getDestinationURL($field,
  353. array('id'=>$this->current_id)).'">'.
  354. $this->columns[$field]['descr'].'</a>';
  355. */
  356. }
  357. function _performDelete($id){
  358. if($this->model){
  359. return $this->model->delete($id);
  360. }
  361. $this->dq->where('id',$id)->do_delete();
  362. }
  363. function format_delete($field){
  364. if(!$this->model)throw new BaseException('delete column requires $dq to be set');
  365. if($id=@$_GET[$this->name.'_'.$field]){
  366. // this was clicked
  367. $this->_performDelete($id);
  368. $this->js()->univ()->successMessage('Deleted Successfully')->getjQuery()->reload()->execute();
  369. }
  370. return $this->format_confirm($field);
  371. }
  372. function init_button($field){
  373. @$this->columns[$field]['thparam'].=' style="width: 40px; text-align: center"';
  374. $this->js(true)->find('.button_'.$field)->button();
  375. }
  376. function setButtonClass($class){
  377. $this->columns[$this->last_column]['button_class']=$class;
  378. }
  379. function init_delete($field){
  380. $this->columns[$field]['button_class']='red';
  381. $g=$this;
  382. $this->api->addHook('post-init',array($this,'_move_delete'),array($field));
  383. /*function() use($g,$field){
  384. });
  385. */
  386. return $this->init_confirm($field);
  387. }
  388. function _move_delete($grid,$field){
  389. if($this->hasColumn($field))$this->addOrder()->move($field,'last')->now();
  390. }
  391. function init_confirm($field){
  392. @$this->columns[$field]['thparam'].=' style="width: 40px; text-align: center"';
  393. $this->js(true)->find('.button_'.$field)->button();
  394. }
  395. function init_prompt($field){
  396. @$this->columns[$field]['thparam'].=' style="width: 40px; text-align: center"';
  397. $this->js(true)->find('.button_'.$field)->button();
  398. }
  399. function format_button($field){
  400. $this->current_row_html[$field]='<button type="button" class="'.$this->columns[$field]['button_class'].'button_'.$field.'" '.
  401. 'onclick="$(this).univ().ajaxec(\''.$this->api->getDestinationURL(null,
  402. array($field=>$this->current_id,$this->name.'_'.$field=>$this->current_id)).'\')">'.
  403. (isset($this->columns[$field]['icon'])?$this->columns[$field]['icon']:'').
  404. $this->columns[$field]['descr'].'</button>';
  405. }
  406. function format_confirm($field){
  407. $this->current_row_html[$field]='<button type="button" class="'.$this->columns[$field]['button_class'].' button_'.$field.'" '.
  408. 'onclick="$(this).univ().confirm(\'Are you sure?\').ajaxec(\''.$this->api->getDestinationURL(null,
  409. array($field=>$this->current_id,$this->name.'_'.$field=>$this->current_id)).'\')">'.
  410. (isset($this->columns[$field]['icon'])?$this->columns[$field]['icon']:'').
  411. $this->columns[$field]['descr'].'</button>';
  412. }
  413. function format_prompt($field){
  414. $this->current_row_html[$field]='<button type="button" class="'.$this->columns[$field]['button_class'].'button_'.$field.'" '.
  415. 'onclick="value=prompt(\'Enter value: \');$(this).univ().ajaxec(\''.$this->api->getDestinationURL(null,
  416. array($field=>$this->current_id,$this->name.'_'.$field=>$this->current_id)).'&value=\'+value)">'.
  417. (isset($this->columns[$field]['icon'])?$this->columns[$field]['icon']:'').
  418. $this->columns[$field]['descr'].'</button>';
  419. }
  420. function init_boolean($field){
  421. @$this->columns[$field]['thparam'].=' style="text-align: center"';
  422. }
  423. function format_boolean($field){
  424. if($this->current_row[$field] && $this->current_row[$field]!='N' && $this->current_row[$field]){
  425. $this->current_row_html[$field]='<div align=center><span class="ui-icon ui-icon-check">yes</span></div>';
  426. }else $this->current_row_html[$field]='';
  427. }
  428. function format_checkbox($field){
  429. $this->current_row_html[$field] = '<input type="checkbox" id="cb_'.
  430. $this->current_id.'" name="cb_'.$this->current_id.
  431. '" value="'.$this->current_id.'"'.
  432. ($this->current_row['selected']=='Y'?" checked ":" ").//'" onclick="'.
  433. //$this->onClick($field).
  434. '/>';
  435. $this->setTDParam($field,'width','10');
  436. $this->setTDParam($field,'align','center');
  437. }
  438. function format_image($field){
  439. $this->current_row_html[$field]='<img src="'.$this->current_row[$field].'"/>';
  440. }
  441. function addRecordOrder($field,$table=''){
  442. if(!$this->record_order){
  443. $this->record_order=$this->add('RecordOrder');
  444. $this->record_order->setField($field,$table);
  445. }
  446. return $this;
  447. }
  448. function staticSortCompare($row1,$row2){
  449. if($this->sortby[0]=='-'){
  450. return strcmp($row2[substr($this->sortby,1)],$row1[substr($this->sortby,1)]);
  451. }
  452. return strcmp($row1[$this->sortby],$row2[$this->sortby]);
  453. }
  454. function applySorting($i,$order,$desc){
  455. if($i instanceof DB_dsql)$i->order($order,$desc);
  456. elseif($i instanceof Model_Table)$i->setOrder($order,$desc);
  457. }
  458. function getIterator(){
  459. $i=parent::getIterator();
  460. if($this->sortby){
  461. $desc=false;
  462. $order=$this->sortby_db;
  463. if(substr($this->sortby_db,0,1)=='-'){
  464. $desc=true;
  465. $order=substr($order,1);
  466. }
  467. $this->applySorting($i,$order,$desc);
  468. }
  469. return $i;
  470. }
  471. function setTemplate($template){
  472. // This allows you to use Template
  473. $this->columns[$this->last_column]['template']=$this->add('SMlite')
  474. ->loadTemplateFromString($template);
  475. return $this;
  476. }
  477. function getFieldStyle($field,$id){
  478. /**
  479. * Returns the structured string with row styles. Used along with getRowContent()
  480. * in row redrawing
  481. */
  482. $style=$this->tdparam[$this->getCurrentIndex()][$field];
  483. $tdparam=null;
  484. if(is_array($style)){
  485. // now we should convert style elements' names to JS compatible
  486. $tdparam=array();
  487. foreach($style as $key=>$value){
  488. switch($key){
  489. //case 'background-color':$tdparam[]="$key:$value";break;
  490. case 'style': case 'css':
  491. // style is a nested array
  492. foreach($value as $k=>$v){
  493. $tdparam[]="$k::$v";
  494. }
  495. break;
  496. default:
  497. $tdparam[]="$key::$value";
  498. }
  499. }
  500. }
  501. return (is_array($tdparam)?join($tdparam,'<s>'):'');
  502. }
  503. function getRowTitle(){
  504. $title=' ';
  505. foreach($this->title_col as $col){
  506. $title.=$this->current_row[$col];
  507. }
  508. if($title==' '){
  509. return "Row #".$this->current_id;
  510. }
  511. return substr($title,1);
  512. }
  513. function getFieldContent($field,$id){
  514. /**
  515. * Returns the properly formatted field content.
  516. * Used firstly with Ajax::reloadExpandedField()
  517. */
  518. // *** Getting required record from DB ***
  519. $idfield=$this->dq->args['fields'][0];
  520. if($idfield=='*'||strpos($idfield,',')!==false)$idfield='id';
  521. $this->dq->where($idfield,$id);
  522. //we should switch off the limit or we won't get any value
  523. $this->dq->limit(1);
  524. $row_data=$this->api->db->getHash($this->dq->select());
  525. // *** Initializing template ***
  526. $this->precacheTemplate(false);
  527. // *** Rendering row ***
  528. $this->current_row=(array)$row_data;
  529. $row=$this->formatRow();
  530. // *** Returning required field value ***
  531. return $row[$field];
  532. }
  533. function applyTDParams($field,$totals=false){
  534. // setting cell parameters (tdparam)
  535. $tdparam=@$this->tdparam[$this->getCurrentIndex()][$field];
  536. $tdparam_str='';
  537. if(is_array($tdparam)){
  538. // wrap is replaced by style property
  539. unset($tdparam['wrap']);
  540. if(is_array($tdparam['style'])){
  541. $tdparam_str.='style="';
  542. foreach($tdparam['style'] as $key=>$value)$tdparam_str.=$key.':'.$value.';';
  543. $tdparam_str.='" ';
  544. unset($tdparam['style']);
  545. }
  546. //walking and combining string
  547. foreach($tdparam as $id=>$value)$tdparam_str.=$id.'="'.$value.'" ';
  548. if($totals)$this->totals_t->set("tdparam_$field",trim($tdparam_str));
  549. else $this->row_t->trySetHTML("tdparam_$field",trim($tdparam_str));
  550. }
  551. }
  552. function setTotalsTitle($field,$title="Total:"){
  553. $this->totals_title_field=$field;
  554. $this->totals_title=$title;
  555. return $this;
  556. }
  557. function formatTotalsRow(){
  558. foreach($this->columns as $tmp=>$column){
  559. $formatters = explode(',',$column['type']);
  560. $all_failed=true;
  561. foreach($formatters as $formatter){
  562. if(method_exists($this,$m="format_totals_".$formatter)){
  563. $all_failed=false;
  564. $this->$m($tmp);
  565. }
  566. }
  567. // setting cell parameters (tdparam)
  568. $this->applyTDParams($tmp,true);
  569. if($all_failed)$this->current_row[$tmp]=$this->totals_value_na;
  570. }
  571. }
  572. function updateTotals(){
  573. parent::updateTotals();
  574. foreach($this->current_row as $key=>$val){
  575. if ((!empty($this->totals_title_field)) and ($key==$this->totals_title_field)) {
  576. $this->totals[$key]=$this->totals_title;
  577. }
  578. }
  579. }
  580. /**
  581. * Adds paginator to the grid
  582. * @param $ipp row count per page
  583. * @param $name if set, paginator will get the name specified. Useful for saving
  584. * different page numbers for different filtering conditions
  585. */
  586. function addPaginator($ipp=25){
  587. // adding ajax paginator
  588. $this->paginator=$this->add('Paginator');
  589. $this->paginator->ipp($ipp);
  590. return $this;
  591. }
  592. public function setWidth( $width ){
  593. $this->template->set('container_style', 'margin: 0 auto; width:'.$width.((!is_numeric($width))?'':'px'));
  594. return $this;
  595. }
  596. public function setNoRecords($message){
  597. $this->no_records_message=$message;
  598. return $this;
  599. }
  600. public function getCurrentIndex($idfield='id'){
  601. // TODO: think more to optimize this method
  602. if(is_array($this->data))return array_search(current($this->data),$this->data);
  603. // else it is dsql dataset...
  604. return $this->current_row[$idfield];
  605. }
  606. public function setTDParam($field,$path,$value){
  607. // adds a parameter. nested ones can be specified like 'style/color'
  608. $path=explode('/',$path);
  609. $current_position=&$this->tdparam[$this->getCurrentIndex()][$field];
  610. if(!is_array($current_position))$current_position=array();
  611. foreach($path as $part){
  612. if(array_key_exists($part,$current_position)){
  613. $current_position=&$current_position[$part];
  614. }else{
  615. $current_position[$part]=array();
  616. $current_position=&$current_position[$part];
  617. }
  618. }
  619. $current_position=$value;
  620. }
  621. public function setTabMovesDown($down=true){
  622. $this->tab_moves_down=$down;
  623. return $this;
  624. }
  625. public function setShowSubmit($show=true){
  626. $this->show_submit=$show;
  627. return $this;
  628. }
  629. /**
  630. * Sets inline properties.
  631. * @param $props - hash with properties: array('tab_moves_down'=>false/true,'show_submit'=>false/true,etc)
  632. * hash keys should replicate local properties names
  633. */
  634. public function setInlineProperties($props){
  635. foreach($props as $key=>$val){
  636. $this->$key=$val;
  637. }
  638. return $this;
  639. }
  640. function addOrder(){
  641. return $this->add('Order','columns')
  642. ->useArray($this->columns)
  643. ;
  644. }
  645. /**
  646. * Adds column on the basis of Model definition
  647. * If $type is passed - column type is replaced by this value
  648. */
  649. function addSelectable($field){
  650. $this->js_widget=null;
  651. $this->js(true)
  652. ->_load('ui.atk4_checkboxes')
  653. ->atk4_checkboxes(array('dst_field'=>$field));
  654. $this->addColumn('checkbox','selected');
  655. $this->addOrder()
  656. ->useArray($this->columns)
  657. ->move('selected','first')
  658. ->now();
  659. }
  660. function addFormatter($field,$formatter){
  661. /*
  662. * add extra formatter to existing field
  663. */
  664. if(!isset($this->columns[$field])){
  665. throw new BaseException('Cannot format nonexistant field '.$field);
  666. }
  667. $this->columns[$field]['type'].=','.$formatter;
  668. if(method_exists($this,$m='init_'.$formatter))$this->$m($field);
  669. return $this;
  670. }
  671. function setFormatter($field,$formatter){
  672. /*
  673. * replace current formatter for field
  674. */
  675. if(!isset($this->columns[$field])){
  676. throw new BaseException('Cannot format nonexistant field '.$field);
  677. }
  678. $this->columns[$field]['type']=$formatter;
  679. if(method_exists($this,$m='init_'.$formatter))$this->$m($field);
  680. $this->last_column=$field;
  681. return $this;
  682. }
  683. /* to reuse td params */
  684. function getAllTDParams(){
  685. return $this->tdparam;
  686. }
  687. }