From e3697322ee62eaa0035863fa17c7803d14ab245a Mon Sep 17 00:00:00 2001 From: Dmitry Pupinin Date: Mon, 2 Nov 2015 10:49:40 +0600 Subject: [PATCH 1/9] Fix bug. Can't pass function name through setCallbacks because it encoding as option --- src/Chumper/Datatable/Table.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Chumper/Datatable/Table.php b/src/Chumper/Datatable/Table.php index 3b114ff..3087075 100644 --- a/src/Chumper/Datatable/Table.php +++ b/src/Chumper/Datatable/Table.php @@ -304,7 +304,7 @@ public function getViewParameters() $this->createMapping(); } return array( - 'options' => $this->convertData(array_merge($this->options, $this->callbacks)), + 'options' => $this->convertData($this->options, $this->callbacks), 'values' => $this->customValues, 'data' => $this->data, 'columns' => array_combine($this->aliasColumns,$this->columns), @@ -325,7 +325,7 @@ public function noScript() return $this; } - private function convertData($options) { + private function convertData($options, $callbacks = null) { $is_obj = false; $first = true; $data = ""; @@ -342,11 +342,7 @@ private function convertData($options) { $data .= json_encode($k) . ":"; } if (is_string($o)) { - if (@preg_match("#^\s*function\s*\([^\)]*#", $o)) { - $data .= $o; - } else { - $data .= json_encode($o); - } + $data .= json_encode($o); } else { if (is_array($o)) { $data .= $this->convertData($o); @@ -355,6 +351,12 @@ private function convertData($options) { } } } + if ($callbacks) { + foreach ($callbacks as $k => $o) { + $data .= empty($data) ? '' : ",\n"; + $data .= json_encode($k) . ":" . $o; + } + } if ($is_obj) { $data = "{ $data }"; @@ -377,7 +379,7 @@ public function script($view = null) } return View::make($this->script_view,array( - 'options' => $this->convertData(array_merge($this->options, $this->callbacks)), + 'options' => $this->convertData($this->options, $this->callbacks), 'id' => $this->idName, )); } From 1853d41b851ff25ea7a6af8802f0e3dad33d3525 Mon Sep 17 00:00:00 2001 From: Dmitry Pupinin Date: Tue, 3 Nov 2015 11:34:42 +0600 Subject: [PATCH 2/9] Bug fix. Wrong count() if groupBy using in query --- src/Chumper/Datatable/Engines/QueryEngine.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Chumper/Datatable/Engines/QueryEngine.php b/src/Chumper/Datatable/Engines/QueryEngine.php index 5a23fc7..6effba4 100644 --- a/src/Chumper/Datatable/Engines/QueryEngine.php +++ b/src/Chumper/Datatable/Engines/QueryEngine.php @@ -73,7 +73,9 @@ public function totalCount() $originalBuilder = $this->removeGroupBy($originalBuilder); } - return $originalBuilder->count(); + return \DB::table(\DB::raw('('.$originalBuilder->toSql().') as temp_tbl')) + ->mergeBindings($originalBuilder->getQuery()) + ->count(); } public function getArray() @@ -126,7 +128,9 @@ protected function internalMake(Collection $columns, array $searchColumns = arra if ($this->options['noGroupByOnCount']) { $countBuilder = $this->removeGroupBy($countBuilder); } - $this->options['counter'] = $countBuilder->count(); + $this->options['counter'] = \DB::table(\DB::raw('('.$countBuilder->toSql().') as temp_tbl')) + ->mergeBindings($countBuilder->getQuery()) + ->count(); } $builder = $this->doInternalOrder($builder, $columns); From 13b2ed014b3c9a33213ad8e9ff15aec1a98601f2 Mon Sep 17 00:00:00 2001 From: Dmitry Pupinin Date: Tue, 3 Nov 2015 12:13:03 +0600 Subject: [PATCH 3/9] searchColumns readme improved --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 62a951c..5b1f136 100644 --- a/README.md +++ b/README.md @@ -276,6 +276,10 @@ Note: If you want to search on number columns with the query engine, then you ca This will cast the columns int the given types when searching on this columns +You also can use dot syntax if your query has identical fields in different tables + ``` + ->searchColumns(array('category.title', 'job.title', 'phone')) + ``` **orderColumns(..$fields)** Will enable the table to allow ordering only in the given columns. From 29dd3fc749897736243d1642cbee4b3789abffb3 Mon Sep 17 00:00:00 2001 From: Dmitry Pupinin Date: Sat, 19 Mar 2016 00:19:54 +0600 Subject: [PATCH 4/9] Fix for 1853d41 (Wrong count() if groupBy using in query) --- src/Chumper/Datatable/Engines/QueryEngine.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Chumper/Datatable/Engines/QueryEngine.php b/src/Chumper/Datatable/Engines/QueryEngine.php index 6effba4..80d7f7b 100644 --- a/src/Chumper/Datatable/Engines/QueryEngine.php +++ b/src/Chumper/Datatable/Engines/QueryEngine.php @@ -74,7 +74,7 @@ public function totalCount() } return \DB::table(\DB::raw('('.$originalBuilder->toSql().') as temp_tbl')) - ->mergeBindings($originalBuilder->getQuery()) + ->mergeBindings($originalBuilder) ->count(); } @@ -129,7 +129,7 @@ protected function internalMake(Collection $columns, array $searchColumns = arra $countBuilder = $this->removeGroupBy($countBuilder); } $this->options['counter'] = \DB::table(\DB::raw('('.$countBuilder->toSql().') as temp_tbl')) - ->mergeBindings($countBuilder->getQuery()) + ->mergeBindings($countBuilder) ->count(); } From 9651e019562561e235b6da09469a917e4dc292e2 Mon Sep 17 00:00:00 2001 From: Dmitry Pupinin Date: Sat, 19 Mar 2016 14:34:32 +0600 Subject: [PATCH 5/9] Allow to pass additional data from server to client on each ajax call. You can get this data using "fnInitComplete" or "fnServerData" or "ajax.json()" or something else. More info: * http://datatables.net/reference/api/ajax.json * http://stackoverflow.com/questions/6090260/jquery-datatables-return-additional-information-from-server --- src/Chumper/Datatable/Engines/BaseEngine.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Chumper/Datatable/Engines/BaseEngine.php b/src/Chumper/Datatable/Engines/BaseEngine.php index d2cfb1b..3d636f9 100644 --- a/src/Chumper/Datatable/Engines/BaseEngine.php +++ b/src/Chumper/Datatable/Engines/BaseEngine.php @@ -123,6 +123,10 @@ abstract class BaseEngine { */ protected $exactWordSearch = false; + /** + * @var mixed Additional data which passed from server to client. + */ + protected $additionalData = null; function __construct() { @@ -240,6 +244,7 @@ public function make() "sEcho" => intval($this->sEcho), "iTotalRecords" => $this->totalCount(), "iTotalDisplayRecords" => $this->count(), + "aaAdditional" => $this->additionalData, ); return Response::json($output); } @@ -330,6 +335,12 @@ public function setExactMatchColumns($columnNames) return $this; } + public function setAdditionalData($data) + { + $this->additionalData = $data; + return $this; + } + public function getRowClass() { return $this->rowClass; From c43caf1a590a3ea19810b7d96d42ab6a6d27e9de Mon Sep 17 00:00:00 2001 From: Dmitry Pupinin Date: Sat, 19 Mar 2016 14:39:41 +0600 Subject: [PATCH 6/9] Allow to display a footer --- src/Chumper/Datatable/Table.php | 18 ++++++++++++++++++ src/views/template.blade.php | 9 +++++++++ 2 files changed, 27 insertions(+) diff --git a/src/Chumper/Datatable/Table.php b/src/Chumper/Datatable/Table.php index 3087075..a23d4bd 100644 --- a/src/Chumper/Datatable/Table.php +++ b/src/Chumper/Datatable/Table.php @@ -58,6 +58,11 @@ class Table { */ protected $className; + /** + * @var String The footer's display mode + */ + protected $footerMode = 'hidden'; + /** * @var String The view used to render the table */ @@ -311,6 +316,7 @@ public function getViewParameters() 'noScript' => $this->noScript, 'id' => $this->idName, 'class' => $this->className, + 'footerMode'=> $this->footerMode, ); } @@ -325,6 +331,18 @@ public function noScript() return $this; } + /** + * Set the footer display mode. + * + * @param $value the one of next values: 'hidden', 'columns', 'empty' + * @return $this + */ + public function showFooter($value = 'columns') + { + $this->footerMode = $value; + return $this; + } + private function convertData($options, $callbacks = null) { $is_obj = false; $first = true; diff --git a/src/views/template.blade.php b/src/views/template.blade.php index d6c2264..b087b8c 100644 --- a/src/views/template.blade.php +++ b/src/views/template.blade.php @@ -11,6 +11,15 @@ @endforeach + @if ($footerMode !== 'hidden') + + + @foreach($columns as $i => $c) + @if($footerMode === 'columns') {{ $c }} @endif + @endforeach + + + @endif @foreach($data as $d) From e648e1539e9f5bd6189c904ad221329cff1a96ef Mon Sep 17 00:00:00 2001 From: Dmitry Pupinin Date: Tue, 24 Mar 2015 12:50:39 +0600 Subject: [PATCH 7/9] Allow sorting on multiple columns using orderData option --- src/Chumper/Datatable/Engines/BaseEngine.php | 30 ++++++++++++------- src/Chumper/Datatable/Engines/QueryEngine.php | 24 +++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/Chumper/Datatable/Engines/BaseEngine.php b/src/Chumper/Datatable/Engines/BaseEngine.php index 3d636f9..88bc00e 100644 --- a/src/Chumper/Datatable/Engines/BaseEngine.php +++ b/src/Chumper/Datatable/Engines/BaseEngine.php @@ -405,14 +405,16 @@ protected function handlesSearch($value) protected function handleiSortCol_0($value) { if(Input::get('sSortDir_0') == 'desc') - $direction = BaseEngine::ORDER_DESC; + $direction[$value] = BaseEngine::ORDER_DESC; else - $direction = BaseEngine::ORDER_ASC; + $direction[$value] = BaseEngine::ORDER_ASC; + $columns = array(); //check if order is allowed if(empty($this->orderColumns)) { - $this->order(array(0 => $value, 1 => $this->getNameByIndex($value)), $direction); + $columns[] = array(0 => $value, 1 => $this->getNameByIndex($value)); + $this->order($columns, $direction); return; } @@ -430,16 +432,22 @@ protected function handleiSortCol_0($value) } } - $i = 0; - foreach($this->columns as $name => $column) - { - if($i == $value && in_array($name, $cleanNames)) - { - $this->order(array(0 => $value, 1 => $this->orderColumns[array_search($name,$cleanNames)]), $direction); - return; + $iSortingCols = Input::get('iSortingCols'); + $sortingCols[] = $value; + for($i = 1; $i < $iSortingCols; $i++) { + $isc = Input::get('iSortCol_'.$i); + $sortingCols[] = $isc; + $direction[$isc] = Input::get('sSortDir_'.$i); + } + + $allColumns = array_keys($this->columns->all()); + foreach ($sortingCols as $num) { + if(in_array($allColumns[$num], $cleanNames)) { + $columns[] = array(0 => $num, 1 => $this->orderColumns[array_search($allColumns[$num],$cleanNames)]); } - $i++; } + $this->order($columns, $direction); + return; } /** diff --git a/src/Chumper/Datatable/Engines/QueryEngine.php b/src/Chumper/Datatable/Engines/QueryEngine.php index 80d7f7b..a29e05d 100644 --- a/src/Chumper/Datatable/Engines/QueryEngine.php +++ b/src/Chumper/Datatable/Engines/QueryEngine.php @@ -286,23 +286,15 @@ private function doInternalOrder($builder, $columns) //var_dump($this->orderColumn); if(!is_null($this->orderColumn)) { - $i = 0; - foreach($columns as $col) - { - - if($i === (int) $this->orderColumn[0]) - { - if(strrpos($this->orderColumn[1], ':')){ - $c = explode(':', $this->orderColumn[1]); - if(isset($c[2])) - $c[1] .= "($c[2])"; - $builder = $builder->orderByRaw("cast($c[0] as $c[1]) ".$this->orderDirection); - } - else - $builder = $builder->orderBy($col->getName(), $this->orderDirection); - return $builder; + foreach ($this->orderColumn as $ordCol) { + if(strrpos($ordCol[1], ':')){ + $c = explode(':', $ordCol[1]); + if(isset($c[2])) + $c[1] .= "($c[2])"; + $builder = $builder->orderByRaw("cast($c[0] as $c[1]) ".$this->orderDirection[$ordCol[0]]); } - $i++; + else + $builder = $builder->orderBy($ordCol[1], $this->orderDirection[$ordCol[0]]); } } return $builder; From 73a8bb8d77ba08a2be5a89fac6c95e80d5f78158 Mon Sep 17 00:00:00 2001 From: Dmitry Pupinin Date: Tue, 24 Mar 2015 15:11:02 +0600 Subject: [PATCH 8/9] New option added 'emptyAtEnd'. Allow sort when empty fields always be at end of table --- src/Chumper/Datatable/Engines/QueryEngine.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Chumper/Datatable/Engines/QueryEngine.php b/src/Chumper/Datatable/Engines/QueryEngine.php index a29e05d..4e65b86 100644 --- a/src/Chumper/Datatable/Engines/QueryEngine.php +++ b/src/Chumper/Datatable/Engines/QueryEngine.php @@ -41,6 +41,7 @@ class QueryEngine extends BaseEngine { 'orderOrder' => null, 'counter' => 0, 'noGroupByOnCount' => false, + 'emptyAtEnd' => false, ); function __construct($builder) @@ -102,6 +103,12 @@ public function setSearchWithAlias() return $this; } + public function setEmptyAtEnd() + { + $this->options['emptyAtEnd'] = true; + return $this; + } + public function setNoGroupByOnCount() { $this->options['noGroupByOnCount'] = true; @@ -291,10 +298,13 @@ private function doInternalOrder($builder, $columns) $c = explode(':', $ordCol[1]); if(isset($c[2])) $c[1] .= "($c[2])"; - $builder = $builder->orderByRaw("cast($c[0] as $c[1]) ".$this->orderDirection[$ordCol[0]]); + $prefix = $this->options['emptyAtEnd'] ? "ISNULL({$c[0]}) asc," : ''; + $builder = $builder->orderByRaw($prefix." cast($c[0] as $c[1]) ".$this->orderDirection[$ordCol[0]]); + } + else { + $prefix = $this->options['emptyAtEnd'] ? "ISNULL({$ordCol[1]}) asc," : ''; + $builder = $builder->orderByRaw($prefix.' '.$ordCol[1].' '.$this->orderDirection[$ordCol[0]]); } - else - $builder = $builder->orderBy($ordCol[1], $this->orderDirection[$ordCol[0]]); } } return $builder; From 4c05bf56dc84bf266dfdbb199a0eb960e387b67a Mon Sep 17 00:00:00 2001 From: Dmitry Pupinin Date: Mon, 28 Mar 2016 15:12:44 +0600 Subject: [PATCH 9/9] Another fix for 1853d41. Different ways for mergeBindings if we use Model or DB facade --- src/Chumper/Datatable/Engines/QueryEngine.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Chumper/Datatable/Engines/QueryEngine.php b/src/Chumper/Datatable/Engines/QueryEngine.php index 4e65b86..775ce85 100644 --- a/src/Chumper/Datatable/Engines/QueryEngine.php +++ b/src/Chumper/Datatable/Engines/QueryEngine.php @@ -74,8 +74,9 @@ public function totalCount() $originalBuilder = $this->removeGroupBy($originalBuilder); } + $qBuilder = $originalBuilder instanceof QueryBuilder ? $originalBuilder : $originalBuilder->getQuery(); return \DB::table(\DB::raw('('.$originalBuilder->toSql().') as temp_tbl')) - ->mergeBindings($originalBuilder) + ->mergeBindings($qBuilder) ->count(); } @@ -135,8 +136,9 @@ protected function internalMake(Collection $columns, array $searchColumns = arra if ($this->options['noGroupByOnCount']) { $countBuilder = $this->removeGroupBy($countBuilder); } + $qBuilder = $countBuilder instanceof QueryBuilder ? $countBuilder : $countBuilder->getQuery(); $this->options['counter'] = \DB::table(\DB::raw('('.$countBuilder->toSql().') as temp_tbl')) - ->mergeBindings($countBuilder) + ->mergeBindings($qBuilder) ->count(); }