1: | <?php |
2: | |
3: | namespace Zippy\Html\DataList; |
4: | |
5: | use Zippy\Html\HtmlComponent; |
6: | use Zippy\Interfaces\Requestable; |
7: | use Zippy\WebApplication; |
8: | |
9: | |
10: | |
11: | |
12: | |
13: | |
14: | class DataTable extends AbstractList implements Requestable |
15: | { |
16: | private $columns = array(); |
17: | private $datalist = array(); |
18: | private $cellevent = null; |
19: | private $cellclickevent = null; |
20: | private $selectedrow = 0; |
21: | private $selectedclass = ""; |
22: | private $maxbuttons = 10; |
23: | private $firstButton = 1; |
24: | private $header = true; |
25: | private $paginator = false; |
26: | private $useajax = false; |
27: | |
28: | public function __construct($id, $DataSource, $header = true, $paginator = false, $useajax = false) { |
29: | AbstractList::__construct($id, $DataSource); |
30: | $this->header = $header; |
31: | $this->paginator = $paginator; |
32: | $this->useajax = $useajax; |
33: | } |
34: | |
35: | |
36: | |
37: | |
38: | final public function RenderImpl() { |
39: | $tag = $this->getTag(); |
40: | |
41: | $tag->appendWith($this->renderHeader()); |
42: | $tag->appendWith($this->renderData()); |
43: | $tag->appendWith($this->renderFooter()); |
44: | } |
45: | |
46: | |
47: | |
48: | |
49: | final public function AddColumn(Column $column) { |
50: | $this->columns[$column->fieldname] = $column; |
51: | } |
52: | |
53: | |
54: | |
55: | |
56: | public function Reload($resetpage = true) { |
57: | parent::Reload($resetpage); |
58: | |
59: | $this->datalist = $this->getItems(); |
60: | } |
61: | |
62: | |
63: | |
64: | |
65: | final public function RequestHandle() { |
66: | $p = WebApplication::$app->getRequest()->request_params[$this->id]; |
67: | if ($p[0] == 'sort') { |
68: | $this->sortf = $p[1]; |
69: | $this->sortd = $p[2]; |
70: | $this->currentpage = 1; |
71: | $this->Reload(); |
72: | } |
73: | if ($p[0] == 'pag') { |
74: | $this->currentpage = $p[1]; |
75: | $this->Reload(false); |
76: | } |
77: | if ($p[0] == 'cellclick' && $this->cellclickevent instanceof \Zippy\Event) { |
78: | $items = array(); |
79: | foreach($this->datalist as $it) { |
80: | $items[$it->getID()]=$it; |
81: | } |
82: | |
83: | |
84: | $this->cellclickevent->onEvent($this, array('dataitem' => $items[$p[2] ], 'field' => $p[1], 'rownumber' => $p[2])); |
85: | $this->setSelectedrow($p[2]); |
86: | } |
87: | |
88: | if ($this->useajax) { |
89: | WebApplication::$app->getResponse()->addAjaxResponse($this->AjaxAnswer()); |
90: | } |
91: | } |
92: | |
93: | |
94: | |
95: | |
96: | final public function setCellDrawEvent(\Zippy\Interfaces\EventReceiver $receiver, $handler) { |
97: | $this->cellevent = new \Zippy\Event($receiver, $handler); |
98: | } |
99: | |
100: | |
101: | |
102: | |
103: | final public function setCellClickEvent(\Zippy\Interfaces\EventReceiver $receiver, $handler) { |
104: | $this->cellclickevent = new \Zippy\Event($receiver, $handler); |
105: | } |
106: | |
107: | |
108: | |
109: | |
110: | private function renderHeader() { |
111: | if (!$this->header) { |
112: | return ""; |
113: | } |
114: | |
115: | $row = "<tr >"; |
116: | |
117: | foreach ($this->columns as $column) { |
118: | |
119: | if (!$column->visible) { |
120: | continue; |
121: | } |
122: | |
123: | $css = strlen($column->headerclass) > 0 ? "class=\"{$column->headerclass}\"" : ""; |
124: | |
125: | |
126: | if ($column->sortable) { |
127: | $sort = ""; |
128: | if ($column->fieldname === $this->sortf) { |
129: | if ($this->sortd === 'asc') { |
130: | $sort = '↓'; |
131: | } else { |
132: | $sort = '↑'; |
133: | } |
134: | } |
135: | $url = $this->getURLNode() . ':sort:' . $column->fieldname . ':' . ($this->sortd === 'asc' ? 'desc' : 'asc'); |
136: | $onclick = "window.location='{$url}'"; |
137: | if ($this->useajax) { |
138: | $onclick = "getUpdate('{$url}&ajax=true');event.returnValue=false; return false;"; |
139: | } |
140: | $row .= ("<th {$css} style=\"white-space: nowrap;cursor:pointer;\" onclick=\"{$onclick}\" ><span>{$column->title}</span> {$sort}</th>"); |
141: | } else { |
142: | |
143: | $row .= ("<th {$css} ><span>{$column->title}</span></th>"); |
144: | } |
145: | } |
146: | $row .= "</tr>"; |
147: | return $row; |
148: | } |
149: | |
150: | |
151: | |
152: | |
153: | private function renderData() { |
154: | |
155: | if (count($this->datalist) == 0) { |
156: | return ""; |
157: | } |
158: | |
159: | $rows = ""; |
160: | foreach ($this->datalist as $item) { |
161: | $rownumber = $item->getID(); |
162: | |
163: | if ($this->selectedrow == $rownumber && $this->selectedclass != "") { |
164: | $row = "<tr class=\"{$this->selectedclass}\" >"; |
165: | } else { |
166: | $row = "<tr >"; |
167: | } |
168: | |
169: | |
170: | foreach ($this->columns as $fieldname => $column) { |
171: | if (!$column->visible) { |
172: | continue; |
173: | } |
174: | |
175: | $data = strlen($item->{$fieldname}) > 0 ? $item->{$fieldname} : $column->defaultdata; |
176: | $css = strlen($column->rowclass) > 0 ? "class=\"{$column->rowclass}\"" : ""; |
177: | $onclick = ""; |
178: | $style = ""; |
179: | |
180: | |
181: | $url = $this->getURLNode() . ':cellclick:' . $fieldname . ':' . $rownumber; |
182: | if ($column->clickable) { |
183: | |
184: | $onclick = "window.location='{$url}'"; |
185: | } |
186: | if ($column->clickable && $this->useajax) { |
187: | $onclick = "getUpdate('{$url}&ajax=true');event.returnValue=false; return false;"; |
188: | } |
189: | |
190: | if (strlen($onclick) > 0) { |
191: | $onclick = " onclick=\"" . $onclick . "\" "; |
192: | $style = "style=\"cursor:pointer;\""; |
193: | } |
194: | |
195: | |
196: | if ($this->cellevent instanceof \Zippy\Event) { |
197: | $userdata = $this->cellevent->onEvent($this, array('dataitem' => $item, 'field' => $fieldname, 'rownumber' => $rownumber)); |
198: | if ($userdata !== null && $userdata !== false) { |
199: | $data = $userdata; |
200: | } |
201: | } |
202: | |
203: | $row .= ("<td {$css} {$onclick} {$style}>{$data}</td>"); |
204: | } |
205: | $row .= "</tr>"; |
206: | $rows .= $row; |
207: | } |
208: | return $rows; |
209: | } |
210: | |
211: | |
212: | |
213: | |
214: | private function renderFooter() { |
215: | if (!$this->paginator) { |
216: | return ""; |
217: | } |
218: | if (count($this->columns) == 0) { |
219: | return ""; |
220: | } |
221: | $currentpage = $this->currentpage; |
222: | |
223: | $content = '<ul class="pagination">'; |
224: | $pages = $this->getPageCount(); |
225: | if ($pages <= 1) { |
226: | return ''; |
227: | } |
228: | |
229: | if ($currentpage - $this->firstButton > $this->maxbuttons) { |
230: | |
231: | $this->firstButton = $currentpage - $this->maxbuttons; |
232: | } |
233: | if ($currentpage < $this->firstButton) { |
234: | $this->firstButton = $currentpage - 1; |
235: | } |
236: | |
237: | if ($this->firstButton > 1) { |
238: | $content .= "<li class=\"page-item\"><a class=\"page-link\" href='void(0);' onclick=\"" . $this->getPaginatorLink(1) . "\"><span aria-hidden=\"true\">«</span></a></li>"; |
239: | $content .= "<li class=\"page-item\"><a class=\"page-link\" href='void(0);' onclick=\"" . $this->getPaginatorLink($currentpage - 1) . "\"><span aria-hidden=\"true\">‹</span></a></li>"; |
240: | $content .= "<li class=\"page-item\"><a class=\"page-link\" href=\"javascript:void(0);\" >…</a></li>"; |
241: | } |
242: | |
243: | |
244: | for ($i = $this->firstButton; $i <= $this->firstButton + $this->maxbuttons; $i++) { |
245: | if ($i > $pages) { |
246: | break; |
247: | } |
248: | if ($currentpage == $i) { |
249: | $content .= "<li class=\"page-item active\"><a class=\"page-link\" href=\"javascript:void(0);\" > {$i} </a></li>"; |
250: | } else { |
251: | $content .= "<li class=\"page-item\"><a class=\"page-link\" href=\"javascript:void(0);\" onclick=\"" . $this->getPaginatorLink($i) . "\"> {$i} </a></li>"; |
252: | } |
253: | } |
254: | |
255: | if ($pages > $this->firstButton + $this->maxbuttons) { |
256: | $content .= "<li class=\"page-item\" ><a class=\"page-link\" href=\"javascript:void(0);\" >…</a></li>"; |
257: | $content .= "<li class=\"page-item\"><a class=\"page-link\" href='void(0);' onclick=\"" . $this->getPaginatorLink($currentpage + 1) . "\"aria-label=\"Next\"> <span aria-hidden=\"true\">›</span></a></li>"; |
258: | $content .= "<li class=\"page-item\"><a class=\"page-link\" href='void(0);' onclick=\"" . $this->getPaginatorLink($pages) . "\"aria-label=\"Next\"> <span aria-hidden=\"true\">»</span></a></li>"; |
259: | } |
260: | |
261: | $countall = $this->getAllRowsCount(); |
262: | $show = $currentpage * $this->pagesize; |
263: | if ($pages == $currentpage) { |
264: | $show = $countall; |
265: | } |
266: | if ($countall <= $this->pagesize) { |
267: | $show = $countall; |
268: | } |
269: | |
270: | $content = "<table ><tr><td valign='middle'>{$show} строк с {$countall} </td><td align='right'> {$content}</td></tr></table>"; |
271: | return "<tr ><td class=\"footercell\" colspan=\"" . count($this->columns) . "\" >{$content}</ul></td></tr>"; |
272: | } |
273: | |
274: | |
275: | |
276: | |
277: | private function getPaginatorLink($pageno) { |
278: | $url = $this->getURLNode() . ':pag:' . $pageno; |
279: | if ($this->useajax) { |
280: | $onclick = "getUpdate('{$url}&ajax=true');event.returnValue=false; return false;"; |
281: | } else { |
282: | $onclick = "window.location='{$url}';event.returnValue=false; return false;"; |
283: | } |
284: | return $onclick; |
285: | } |
286: | |
287: | |
288: | |
289: | |
290: | |
291: | |
292: | |
293: | |
294: | public function setSelectedrow($number) { |
295: | $this->selectedrow = $number; |
296: | } |
297: | |
298: | |
299: | |
300: | |
301: | |
302: | public function getSelectedRow() { |
303: | return $this->selectedRow; |
304: | } |
305: | |
306: | |
307: | |
308: | |
309: | |
310: | |
311: | public function setSelectedClass($selectedclass) { |
312: | $this->selectedclass = $selectedclass; |
313: | } |
314: | |
315: | |
316: | |
317: | |
318: | |
319: | public function removeAllColumns() { |
320: | $this->columns = array(); |
321: | } |
322: | |
323: | } |
324: | |
325: | |
326: | class Column |
327: | { |
328: | public function __construct($fieldname, $title, $sortable = false, $visible = true, $clickable = false, $headerclass = "", $rowclass = "", $defaultdata = "") { |
329: | $this->fieldname = $fieldname; |
330: | $this->visible = $visible; |
331: | $this->sortable = $sortable; |
332: | $this->clickable = $clickable; |
333: | $this->title = $title; |
334: | $this->headerclass = $headerclass; |
335: | $this->defaultdata = $defaultdata; |
336: | $this->rowclass = $rowclass; |
337: | } |
338: | |
339: | public $visible = true; |
340: | public $sortable = false; |
341: | public $clickable = false; |
342: | public $fieldname = ""; |
343: | public $title = ""; |
344: | public $headerclass = ""; |
345: | public $rowclass = ""; |
346: | public $defaultdata = " "; |
347: | |
348: | } |
349: | |
350: | |
351: | |
352: | |
353: | |
354: | |
355: | |
356: | |