phpMv -UI toolkit 2.4.12
jQuery, jQuery UI, Twitter Bootstrap and Semantic-UI library for php & php MVC Frameworks
Loading...
Searching...
No Matches
DataTable.php
Go to the documentation of this file.
1<?php
3
18
28
29 protected $_searchField;
30
31 protected $_urls;
32
33 protected $_pagination;
34
35 protected $_compileParts;
36
38
39 protected $_editBehavior;
40
42
43 protected $_visibleHover = false;
44
46
48
49 protected $_emptyMessage;
50
51 protected $_json;
52
53 protected $_rowClass = "_element";
54
55 protected $_sortable;
56
57 protected $_hiddenColumns;
58
59 protected $_colWidths;
60
62
63 protected $_caption;
64
65 protected $_namePrefix;
66
67 public function __construct($identifier, $model, $modelInstance = NULL) {
68 parent::__construct($identifier, $model, $modelInstance);
69 $this->_init(new InstanceViewer($identifier), "table", new HtmlTable($identifier, 0, 0), false);
70 $this->_urls = [];
71 $this->_emptyMessage = new HtmlMessage("", "nothing to display");
72 $this->_emptyMessage->setIcon("info circle");
73 }
74
75 public function run(JsUtils $js) {
76 if ($this->_runned !== true) {
77 $offset = $js->scriptCount();
78 if ($this->_hasCheckboxes && isset($js)) {
79 $this->_runCheckboxes($js);
80 }
81 if ($this->_visibleHover) {
82 $js->execOn("mouseover", "#" . $this->identifier . " tr", "$(event.currentTarget).closest('tr').find('.visibleover').css('visibility', 'visible');", [
83 "preventDefault" => false,
84 "stopPropagation" => true
85 ]);
86 $js->execOn("mouseout", "#" . $this->identifier . " tr", "$(event.currentTarget).closest('tr').find('.visibleover').css('visibility', 'hidden');$(event.currentTarget).trigger('visibleoverOut');", [
87 "preventDefault" => false,
88 "stopPropagation" => true
89 ]);
90 }
91 if (\is_array($this->_deleteBehavior))
92 $this->_generateBehavior("delete", $this->_deleteBehavior, $js);
93 if (\is_array($this->_editBehavior))
94 $this->_generateBehavior("edit", $this->_editBehavior, $js);
95 if (\is_array($this->_displayBehavior)) {
96 $this->_generateBehavior("display", $this->_displayBehavior, $js);
97 }
98 parent::run($js);
99 if (isset($this->_pagination)) {
100 $this->_associatePaginationBehavior($js, $offset);
101 }
102 $this->_associateSearchFieldBehavior($js, $offset);
103 $this->_runned = true;
104 }
105 }
106
107 protected function _generateBehavior($op, $params, JsUtils $js) {
108 if (isset($this->_urls[$op])) {
109 $params = \array_merge($params, [
110 "attr" => "data-ajax"
111 ]);
112 $js->ajaxOnClick("#" . $this->identifier . " ._" . $op, $this->_urls[$op], $this->getTargetSelector($op), $params);
113 }
114 }
115
121 protected function getTable() {
122 return $this->content["table"];
123 }
124
125 public function refreshTR() {
126 $this->getTable()->refreshTR();
127 return $this;
128 }
129
130 public function refreshTD($fieldName, $jquery, $view) {
131 $index = $this->_getIndex($fieldName);
132 $this->compile($jquery, $view);
133 return $this->refreshTR()
134 ->getTable()
135 ->getCell(0, $index);
136 }
137
138 public function compile(JsUtils $js = NULL, &$view = NULL) {
139 if (! $this->_generated) {
140 if (isset($this->_buttonsColumn)) {
141 $this->_instanceViewer->sortColumnContent($this->_buttonsColumn, $this->_buttons);
142 }
143 $this->_instanceViewer->setInstance($this->_model);
144 $captions = $this->_instanceViewer->getCaptions();
145 $table = $this->content["table"];
146 if ($this->_hasCheckboxes) {
147 $this->_generateMainCheckbox($captions);
148 }
149 $table->setRowCount(0, \count($captions));
150 $this->_generateHeader($table, $captions);
151
152 if (isset($this->_compileParts))
153 $table->setCompileParts($this->_compileParts);
154
155 $this->_generateContent($table);
156
157 $this->compileExtraElements($table, $captions);
158 $this->_compileSearchFieldBehavior($js);
159
160 $this->content = JArray::sortAssociative($this->content, [
162 "table",
164 ]);
165 if ($this->_caption != null) {
166 $this->wrap("<div class='field'><label>{$this->_caption}</label>", "</div>");
167 }
168 $this->_compileForm();
169 $this->_applyStyleAttributes($table);
170 $this->_generated = true;
171 }
172 return parent::compile($js, $view);
173 }
174
175 protected function compileExtraElements($table, $captions) {
176 if ($this->_hasCheckboxes && $table->hasPart("thead")) {
177 $table->getHeader()
178 ->getCell(0, 0)
179 ->addClass("no-sort");
180 }
181
182 if (isset($this->_toolbar)) {
183 $this->_setToolbarPosition($table, $captions);
184 }
185 if (isset($this->_pagination) && $this->_pagination->getVisible()) {
186 $this->_generatePagination($table);
187 }
188 }
189
190 protected function _applyStyleAttributes($table) {
191 if (isset($this->_hiddenColumns))
192 $this->_hideColumns();
193 if (isset($this->_colWidths)) {
194 foreach ($this->_colWidths as $colIndex => $width) {
195 $table->setColWidth($colIndex, $width);
196 }
197 }
198 }
199
200 protected function _hideColumns() {
201 foreach ($this->_hiddenColumns as $colIndex) {
202 $this->_self->hideColumn($colIndex);
203 }
204 return $this;
205 }
206
207 protected function _generateHeader(HtmlTable $table, $captions) {
208 $gbFields = $this->_instanceViewer->getGroupByFields();
209 if (\is_array($gbFields)) {
210 $captions = \array_values(JArray::removeByKeys($captions, $gbFields));
211 }
212 $table->setHeaderValues($captions);
213 if (isset($this->_sortable)) {
214 $table->setSortable($this->_sortable);
215 }
216 }
217
218 protected function _generateContent($table) {
219 $objects = $this->_modelInstance;
220 if (isset($this->_pagination)) {
221 $objects = $this->_pagination->getObjects($this->_modelInstance);
222 }
223 InstanceViewer::setIndex(0);
224 $fields = $this->_instanceViewer->getSimpleProperties();
225 $groupByFields = $this->_instanceViewer->getGroupByFields();
226 if (! \is_array($groupByFields)) {
227 $table->fromDatabaseObjects($objects, function ($instance) use ($table, $fields) {
228 return $this->_generateRow($instance, $fields, $table);
229 });
230 } else {
231 $diffFields = \array_values(JArray::removeByKeys($fields, $groupByFields));
232 $activeValues = \array_combine($groupByFields, \array_fill(0, \count($groupByFields), null));
233 $uuids = [];
234 $table->fromDatabaseObjects($objects, function ($instance) use ($table, $fields, &$activeValues, $groupByFields, &$uuids, $diffFields) {
235 $this->_instanceViewer->setInstance($instance);
236 foreach ($groupByFields as $index => $gbField) {
237 $this->_generateGroupByRow($index, $gbField, $table, $fields, $activeValues, $uuids);
238 }
239 return $this->_generateRow($instance, $diffFields, $table, null, $uuids);
240 });
241 }
242 if ($table->getRowCount() == 0) {
243 $result = $table->addRow();
244 $result->mergeCol();
245 $result->setValues([
246 $this->_emptyMessage
247 ]);
248 }
249 }
250
251 protected function _generateGroupByRow($index, $gbField, $table, $fields, &$activeValues, &$uuids) {
252 $newValue = $this->_instanceViewer->getValue($gbField);
253 if ($this->getElementContent($activeValues[$gbField]) !== $this->getElementContent($newValue)) {
254 if ($index == 0) {
255 $uuids = [];
256 }
257 $uuid = \uniqid("grp");
258 $uuids[$gbField] = $uuid;
259 $id = $this->_instanceViewer->getIdentifier();
260 $result = $table->addMergeRow(\count($fields) + 1, $newValue);
261 $result->setIdentifier($this->identifier . "-tr-gb-" . $id);
262 $result->setProperty("data-ajax", $id);
263 $result->setProperty("data-group", $uuid);
264 $result->addToProperty("class", $this->_rowClass);
265 $activeValues[$gbField] = $newValue;
266 }
267 }
268
269 private function getElementContent($elm) {
270 if ($elm instanceof HtmlDoubleElement) {
271 return $elm->getTextContent();
272 }
273 return $elm;
274 }
275
276 public function getFieldValue($index) {
277 $index = $this->_getIndex($index);
278 if (\is_numeric($index)) {
279 $values = $this->_instanceViewer->getValues();
280 if (isset($values[$index])) {
281 return $values[$index];
282 }
283 }
284 return null;
285 }
286
287 protected function _generateRow($instance, $fields, &$table, $checkedClass = null, $uuids = null) {
288 $this->_instanceViewer->setInstance($instance);
289 InstanceViewer::$index ++;
290 $values = $this->_instanceViewer->getValues();
291 $id = $this->_instanceViewer->getIdentifier();
292 $dataAjax = $id;
293 $id = $this->cleanIdentifier($id);
294 if ($this->_hasCheckboxes) {
295 $ck = new HtmlCheckbox("ck-" . $this->identifier . "-" . $id, "");
296 $checked = false;
297 if (isset($this->_checkedCallback)) {
299 $checked = $func($instance);
300 }
301 $ck->setChecked($checked);
302 $field = $ck->getField();
303 $field->setProperty("value", $dataAjax);
304 $field->setProperty("name", "selection[]");
305 if (isset($checkedClass))
306 $field->setClass($checkedClass);
307 \array_unshift($values, $ck);
308 }
309 $result = $table->newRow();
310 $result->setIdentifier($this->identifier . "-tr-" . $id);
311 $result->setProperty("data-ajax", $dataAjax);
312 $result->setValues($values);
313 $result->addToProperty("class", $this->_rowClass);
314 $result->setPropertyValues("data-field", $fields);
315 if (isset($uuids)) {
316 $result->setProperty("data-child", implode(" ", $uuids));
317 }
318 return $result;
319 }
320
321 protected function _generatePagination($table) {
322 if (isset($this->_toolbar)) {
323 if ($this->_toolbarPosition == PositionInTable::FOOTER)
324 $this->_toolbar->setFloated("left");
325 }
326 $footer = $table->getFooter();
327 $footer->mergeCol();
328 $this->_paginationToolbar = $this->_pagination->generateMenu($this->identifier);
329 $footer->addValues($this->_paginationToolbar);
330 }
331
332 protected function _associatePaginationBehavior(JsUtils $js = NULL, $offset = null) {
333 if (isset($this->_urls["refresh"])) {
334 $menu = $this->_pagination->getMenu();
335 if (isset($menu) && isset($js)) {
336 $js->postOnClick("#" . $menu->getIdentifier() . " .item", $this->_urls["refresh"], "{'p':$(this).attr('data-page'),'_model':'" . JString::doubleBackSlashes($this->_model) . "'}", $this->getRefreshSelector(), [
337 "preventDefault" => false,
338 "jqueryDone" => "replaceWith",
339 "hasLoader" => false,
340 "jsCallback" => '$("#' . $this->identifier . '").trigger("pageChange");$("#' . $this->identifier . '").trigger("activeRowChange");'
341 ]);
342 $page = $_POST["p"] ?? null;
343 if (isset($page)) {
344 $activeClass = $this->getActiveRowClass();
345 $js->execAtLast('$("#' . $this->getIdentifier() . ' .pagination").children("a.item").removeClass("' . $activeClass . '");$("#' . $this->getIdentifier() . ' .pagination").children("a.item[data-page=' . $page . ']:not(.no-active)").addClass("' . $activeClass . '");');
346 }
347 }
348 }
349 }
350
351 protected function _compileSearchFieldBehavior(JsUtils $js = NULL) {
352 if (isset($this->_searchField) && isset($js) && isset($this->_urls["refresh"])) {
353 $this->_searchField->postOn("change", $this->_urls["refresh"], "{'s':$(self).val(),'_model':'" . JString::doubleBackSlashes($this->_model) . "'}", "#" . $this->identifier . " tbody", [
354 "preventDefault" => false,
355 "jqueryDone" => "replaceWith",
356 "hasLoader" => "internal",
357 "jsCallback" => '$("#' . $this->identifier . '").trigger("searchTerminate",[$(self).val()]);'
358 ]);
359 }
360 }
361
362 protected function _associateSearchFieldBehavior(JsUtils $js = NULL, $offset = null) {}
363
364 protected function _getFieldName($index) {
365 $fieldName = parent::_getFieldName($index);
366 if (\is_object($fieldName))
367 $fieldName = "field-" . $index;
368 if ($this->_namePrefix != null) {
369 $fieldName = $this->_namePrefix . '.' . $fieldName;
370 }
371 return $fieldName . "[]";
372 }
373
374 protected function _getFieldCaption($index) {
375 return null;
376 }
377
378 protected function applyToolbarPosition(string $position, $table, $captions = NULL) {
379 switch ($position) {
382 if (isset($this->_compileParts) === false) {
383 $this->content[$position] = $this->_toolbar;
384 }
385 break;
389 $this->addToolbarRow($position, $table, $captions);
390 break;
391 }
392 }
393
394 protected function _setToolbarPosition($table, $captions = NULL) {
395 if (\is_array($this->_toolbarPosition)) {
396 foreach ($this->_toolbarPosition as $tbp) {
397 $this->applyToolbarPosition($tbp, $table, $captions);
398 }
399 } else {
400 $this->applyToolbarPosition($this->_toolbarPosition, $table, $captions);
401 }
402 }
403
414 public function afterCompile($index, $callback) {
415 $this->_instanceViewer->afterCompile($index, $callback);
416 return $this;
417 }
418
419 private function addToolbarRow($part, $table, $captions) {
420 $hasPart = $table->hasPart($part);
421 if ($hasPart) {
422 $row = $table->getPart($part)->addRow(\count($captions));
423 } else {
424 $row = $table->getPart($part)->getRow(0);
425 }
426 $row->mergeCol();
427 $row->setValues([
428 $this->_toolbar
429 ]);
430 }
431
438 public function getHtmlComponent() {
439 return $this->content["table"];
440 }
441
442 public function getUrls() {
443 return $this->_urls;
444 }
445
454 public function setUrls($urls) {
455 if (\is_array($urls)) {
456 $this->_urls["refresh"] = JArray::getValue($urls, "refresh", 0);
457 $this->_urls["edit"] = JArray::getValue($urls, "edit", 1);
458 $this->_urls["delete"] = JArray::getValue($urls, "delete", 2);
459 $this->_urls["display"] = JArray::getValue($urls, "display", 3);
460 } else {
461 $this->_urls = [
462 "refresh" => $urls,
463 "edit" => $urls,
464 "delete" => $urls,
465 "display" => $urls
466 ];
467 }
468 return $this;
469 }
470
484 public function paginate($page, $total_rowcount, $items_per_page = 10, $pages_visibles = null) {
485 $this->_pagination = new Pagination($items_per_page, $pages_visibles, $page, $total_rowcount);
486 return $this;
487 }
488
500 public function autoPaginate($page = 1, $items_per_page = 10, $pages_visibles = 4) {
501 $this->_pagination = new Pagination($items_per_page, $pages_visibles, $page);
502 return $this;
503 }
504
510 public function refresh($compileParts = [
511 'tbody'
512 ]) {
513 $this->_compileParts = $compileParts;
514 return $this;
515 }
516
523 public function addSearchInToolbar($position = Direction::RIGHT) {
524 return $this->addInToolbar($this->getSearchField())
525 ->setPosition($position);
526 }
527
528 public function getSearchField() {
529 if (isset($this->_searchField) === false) {
530 $this->_searchField = new HtmlInput("search-" . $this->identifier, "search", "", "Search...");
531 $this->_searchField->addIcon("search", Direction::RIGHT);
532 }
533 return $this->_searchField;
534 }
535
543 public function onNewRow($callback) {
544 $this->content["table"]->onNewRow($callback);
545 return $this;
546 }
547
553 public function asForm() {
554 return $this->getForm();
555 }
556
557 protected function getTargetSelector($op) {
558 $result = $this->_targetSelector;
559 if (! isset($result[$op]))
560 $result = "#" . $this->identifier;
561 return $result[$op];
562 }
563
572 if (! \is_array($_targetSelector)) {
574 "edit" => $_targetSelector,
575 "delete" => $_targetSelector
576 ];
577 }
578 $this->_targetSelector = $_targetSelector;
579 return $this;
580 }
581
582 public function getRefreshSelector() {
583 if (isset($this->_refreshSelector))
585 return "#" . $this->identifier . " tbody";
586 }
587
594 $this->_refreshSelector = $_refreshSelector;
595 return $this;
596 }
597
603 public function show($modelInstance) {
604 if (\is_array($modelInstance)) {
605 if (isset($modelInstance[0]) && \is_array(array_values($modelInstance)[0]))
606 $modelInstance = \json_decode(\json_encode($modelInstance), FALSE);
607 }
608 $this->_modelInstance = $modelInstance;
609 }
610
611 public function getRowClass() {
612 return $this->_rowClass;
613 }
614
621 public function setRowClass($_rowClass) {
622 $this->_rowClass = $_rowClass;
623 return $this;
624 }
625
633 $this->_emptyMessage = $_emptyMessage;
634 return $this;
635 }
636
637 public function setSortable($colIndex = NULL) {
638 $this->_sortable = $colIndex;
639 return $this;
640 }
641
642 public function setActiveRowSelector($class = "active", $event = "click", $multiple = false) {
643 $this->_self->setActiveRowSelector($class, $event, $multiple);
644 return $this;
645 }
646
647 public function getActiveRowClass() {
648 return $this->_self->getActiveRowClass();
649 }
650
651 public function hasActiveRowSelector() {
652 return $this->_self->hasActiveRowSelector();
653 }
654
655 public function hideColumn($colIndex) {
656 if (! \is_array($this->_hiddenColumns))
657 $this->_hiddenColumns = [];
658 $this->_hiddenColumns[] = $colIndex;
659 return $this;
660 }
661
662 public function setColWidth($colIndex, $width) {
663 $this->_colWidths[$colIndex] = $width;
664 return $this;
665 }
666
667 public function setColWidths($_colWidths) {
668 $this->_colWidths = $_colWidths;
669 return $this;
670 }
671
672 public function setColAlignment($colIndex, $alignment) {
673 $this->content["table"]->setColAlignment($colIndex, $alignment);
674 return $this;
675 }
676
677 public function trigger($event, $params = "[]") {
678 return $this->getHtmlComponent()->trigger($event, $params);
679 }
680
681 public function onActiveRowChange($jsCode) {
682 $this->getHtmlComponent()->onActiveRowChange($jsCode);
683 return $this;
684 }
685
690 public function getDeleteBehavior() {
692 }
693
698 public function getEditBehavior() {
700 }
701
706 public function getDisplayBehavior() {
708 }
709
715 $this->_displayBehavior = $_displayBehavior;
716 }
717
722 public function getGroupByFields() {
723 return $this->_instanceViewer->getGroupByFields();
724 }
725
730 public function setGroupByFields($_groupByFields) {
731 $this->_instanceViewer->setGroupByFields($_groupByFields);
732 }
733
734 public function addGroupBy($index) {
735 $index = $this->_getIndex($index);
736 if ($index !== false) {
737 $this->_instanceViewer->addGroupBy($index);
738 }
739 }
740
746 $this->_visibleHover = $_visibleHover;
747 }
748
753 public function getPaginationToolbar() {
755 }
756
757 public function setInverted($recursive = true) {
758 $this->getHtmlComponent()->setInverted($recursive);
759 if ($this->_emptyMessage instanceof HtmlSemDoubleElement) {
760 $this->_emptyMessage->setInverted($recursive);
761 }
762 }
763
764 public function setFocusable(bool $focusable) {
765 $this->content["table"]->setFocusable($focusable);
766 }
767
768 public function setFormCaption($caption) {
769 $this->_caption = $caption;
770 }
771
776 public function getNamePrefix() {
777 return $this->_namePrefix;
778 }
779
784 public function setNamePrefix($namePrefix): void {
785 $this->_namePrefix = $namePrefix;
786 }
787}
JQuery PHP library.
Definition JsUtils.php:23
addInToolbar($element, $callback=NULL)
Adds a new element in toolbar.
Definition Widget.php:268
_init($instanceViewer, $contentKey, $content, $edition)
Definition Widget.php:81
_getIndex($fieldName)
Definition Widget.php:96
wrap($before, $after="")
Definition BaseHtml.php:170
execOn($event, $element, $js, $parameters=array())
Executes the javascript code $js when $event fires on $element.
ajaxOnClick($element, $url, $responseElement='', $parameters=array())
Performs a get to $url on the click event on $element and display it in $responseElement.
Base class for Semantic double elements.
setHeaderValues($values=array())
Sets the header values.
DataTable widget for displaying list of objects.
Definition DataTable.php:27
run(JsUtils $js)
SimpleExtComponent\Ajax\common\html\BaseHtmlrun()\Ajax\common\html\BaseHtmlrun()\Ajax\common\html\Bas...
Definition DataTable.php:75
setActiveRowSelector($class="active", $event="click", $multiple=false)
__construct($identifier, $model, $modelInstance=NULL)
Definition DataTable.php:67
applyToolbarPosition(string $position, $table, $captions=NULL)
refreshTD($fieldName, $jquery, $view)
afterCompile($index, $callback)
Associates a $callback function after the compilation of the field at $index position The $callback f...
_associateSearchFieldBehavior(JsUtils $js=NULL, $offset=null)
setUrls($urls)
Sets the associative array of urls for refreshing, updating or deleting think of defining the update ...
_associatePaginationBehavior(JsUtils $js=NULL, $offset=null)
_setToolbarPosition($table, $captions=NULL)
setEmptyMessage($_emptyMessage)
Sets the message displayed when there is no record.
addSearchInToolbar($position=Direction::RIGHT)
Adds a search input in toolbar.
_generateBehavior($op, $params, JsUtils $js)
setInverted($recursive=true)
can be formatted to appear on dark backgrounds
setRowClass($_rowClass)
Sets the default row class (tr class)
_generateGroupByRow($index, $gbField, $table, $fields, &$activeValues, &$uuids)
compile(JsUtils $js=NULL, &$view=NULL)
_generateHeader(HtmlTable $table, $captions)
addToolbarRow($part, $table, $captions)
setTargetSelector($_targetSelector)
Sets the response element selector for Edit and Delete request with ajax.
paginate($page, $total_rowcount, $items_per_page=10, $pages_visibles=null)
Paginates the DataTable element with a Semantic HtmlPaginationMenu component.
asForm()
Returns a form corresponding to the Datatable.
onNewRow($callback)
The callback function called after the insertion of each row when fromDatabaseObjects is called callb...
autoPaginate($page=1, $items_per_page=10, $pages_visibles=4)
Auto Paginates the DataTable element with a Semantic HtmlPaginationMenu component.
_generateRow($instance, $fields, &$table, $checkedClass=null, $uuids=null)