diff --git a/lam/graphics/downarrows-black.png b/lam/graphics/downarrows-black.png new file mode 100644 index 00000000..644428ad Binary files /dev/null and b/lam/graphics/downarrows-black.png differ diff --git a/lam/graphics/downarrows.png b/lam/graphics/downarrows.png new file mode 100644 index 00000000..8507145c Binary files /dev/null and b/lam/graphics/downarrows.png differ diff --git a/lam/graphics/uparrows-black.png b/lam/graphics/uparrows-black.png new file mode 100644 index 00000000..8573bdc2 Binary files /dev/null and b/lam/graphics/uparrows-black.png differ diff --git a/lam/graphics/uparrows.png b/lam/graphics/uparrows.png new file mode 100644 index 00000000..76478479 Binary files /dev/null and b/lam/graphics/uparrows.png differ diff --git a/lam/lib/html.inc b/lam/lib/html.inc index a947f903..e6d38819 100644 --- a/lam/lib/html.inc +++ b/lam/lib/html.inc @@ -2040,6 +2040,8 @@ class htmlInputCheckbox extends htmlElement { protected $elementsToEnable = array(); /** list of input elements to disable when checked */ protected $elementsToDisable = array(); + /** onclick event code */ + private $onClick; /** @@ -2167,7 +2169,11 @@ class htmlInputCheckbox extends htmlElement { if (!empty($onChange)) { $onChange = ' onChange="' . $onChange . '"'; } - echo ''; + $onClick = ''; + if (!empty($this->onClick)) { + $onClick = ' onclick="' . $this->onClick . '"'; + } + echo ''; echo $script; if ($this->transient) { return array(); @@ -2250,6 +2256,15 @@ class htmlInputCheckbox extends htmlElement { return 'tr'; } + /** + * Sets the onclick code. + * + * @param string $code JS code + */ + public function setOnClick($code) { + $this->onClick = $code; + } + } /** @@ -4663,6 +4678,10 @@ class htmlResponsiveTable extends htmlElement { /** highlighted rows */ private $highlighted = array(); + /** CSS class for odd row numbers */ + private $cssOddRow; + /** CSS class for even row numbers */ + private $cssEvenRow; /** * Creates the table. @@ -4689,7 +4708,8 @@ class htmlResponsiveTable extends htmlElement { $classes[] = 'responsive-table'; echo ''; echo ''; - echo ''; + $headClass = empty($this->cssOddRow) ? '' : ' class="' . $this->cssOddRow . '"'; + echo ''; $counter = 0; foreach ($this->titles as $title) { $width = ''; @@ -4706,8 +4726,18 @@ class htmlResponsiveTable extends htmlElement { $counter = 0; foreach ($this->data as $row) { $cssClass = ''; + $cssClasses = array(); if (in_array($counter, $this->highlighted)) { - $cssClass = ' class="bold"'; + $cssClasses[] = 'bold'; + } + if (!empty($this->cssEvenRow) && ($counter % 2 === 0)) { + $cssClasses[] = $this->cssEvenRow; + } + if (!empty($this->cssOddRow) && ($counter % 2 === 1)) { + $cssClasses[] = $this->cssOddRow; + } + if (!empty($cssClasses)) { + $cssClass = ' class="' . implode(' ', $cssClasses) . '"'; } echo ''; for ($i = 0; $i < $titleCount; $i++) { @@ -4728,6 +4758,18 @@ class htmlResponsiveTable extends htmlElement { $this->widths = $widths; } + /** + * Sets the CSS classes for odd and even rows. + * The title row counts as row number -1. + * + * @param string $oddClass class for odd rows + * @param string $evenClass class for even rows + */ + public function setRowClasses($oddClass, $evenClass) { + $this->cssOddRow = $oddClass; + $this->cssEvenRow = $evenClass; + } + } diff --git a/lam/lib/lists.inc b/lam/lib/lists.inc index 141260f5..0003e85c 100644 --- a/lam/lib/lists.inc +++ b/lam/lib/lists.inc @@ -202,6 +202,7 @@ class lamList { $this->listDrawNavigationBar(sizeof($this->entries)); echo ("
\n"); echo "
"; + $this->printAccountTable($this->entries); // account table head $this->listPrintTableHeader(); // account table body @@ -215,6 +216,8 @@ class lamList { // navigation bar $this->listDrawNavigationBar(sizeof($this->entries)); echo ("
\n"); + $accounts = array(); + $this->printAccountTable($accounts); // account table head $this->listPrintTableHeader(); echo "

\n"; @@ -388,11 +391,105 @@ class lamList { protected function getFilterAsTextForURL() { $text = ''; foreach ($this->filters as $attr => $filter) { - $text .= "&filter" . strtolower($attr) . '=' . $filter; + $text .= "&filter" . strtolower($attr) . '=' . $filter; } return $text; } + /** + * Prints the entry list + * + * @param array $info entries + */ + private function printAccountTable(&$info) { + $scope = $this->type->getScope(); + $titles = $this->descArray; + array_unshift($titles, _('Actions')); + $data = array(); + $data[] = $this->getSortingElements(); + $data[] = $this->getFilterElements(); + + $table = new htmlResponsiveTable($titles, $data); + $table->setRowClasses($scope . '-dark', $scope . '-bright'); + $table->setCSSClasses(array($scope . '-border accountlist')); + + parseHtml(null, $table, array(), false, $this->tabindex, $scope); + } + + /** + * Returns the elements to show in sorting row. + * + * @return htmlElement[] elements + */ + private function getSortingElements() { + $filter = $this->getFilterAsTextForURL(); + $sortElements = array(new htmlOutputText(_('Sort sequence'))); + foreach ($this->attrArray as $attributeName) { + $link = "list.php?type=" . $this->type->getId() . "&". + "sort=" . strtolower($attributeName) . $filter . "&norefresh=y"; + $buttons = new htmlGroup(); + if (strtolower($attributeName) == $this->sortColumn) { + if ($this->sortDirection < 0) { + $buttons->addElement(new htmlLink(null, $link . '&sortdirection=1', '../../graphics/downarrows.png')); + $buttons->addElement(new htmlLink(null, $link . '&sortdirection=-1', '../../graphics/uparrows-black.png')); + } + else { + $buttons->addElement(new htmlLink(null, $link . '&sortdirection=1', '../../graphics/downarrows-black.png')); + $buttons->addElement(new htmlLink(null, $link . '&sortdirection=-1', '../../graphics/uparrows.png')); + } + } + else { + $buttons->addElement(new htmlLink(null, $link . '&sortdirection=1', '../../graphics/downarrows.png')); + $buttons->addElement(new htmlLink(null, $link . '&sortdirection=-1', '../../graphics/uparrows.png')); + } + $sortElements[] = $buttons; + } + return $sortElements; + } + + /** + * Returns the elements to show in filter row. + * + * @return htmlElement[] elements + */ + private function getFilterElements() { + $actionElement = new htmlGroup(); + $selectAll = new htmlInputCheckbox('tableSelectAll', false); + $selectAll->setCSSClasses(array('align-middle')); + $selectAll->setOnClick('list_switchAccountSelection();'); + $actionElement->addElement($selectAll); + $actionElement->addElement(new htmlSpacer('1rem', null)); + $actionElement->addElement(new htmlOutputText(_('Filter'))); + $filterButton = new htmlButton('apply_filter', 'filter.png', true); + $filterButton->setTitle(_("Here you can input simple filter expressions (e.g. 'value' or 'v*'). The filter is case-insensitive.")); + $actionElement->addElement($filterButton); + if (sizeof($this->filters) > 0) { + $clearFilterButton = new htmlButton('clear_filter', 'clearFilter.png', true); + $clearFilterButton->setTitle(_('Clear filter')); + $actionElement->addElement($clearFilterButton); + } + + $filterElements = array($actionElement); + $clearFilter = isset($_POST['clear_filter']); + foreach ($this->attrArray as $attributeName) { + $attributeName = strtolower($attributeName); + if ($this->canBeFiltered($attributeName)) { + $value = ""; + if (!$clearFilter && isset($this->filters[$attributeName])) { + $value = $this->filters[$attributeName]; + } + $filterInput = new htmlInputField('filter' . $attributeName, $value); + $filterInput->setCSSClasses(array($this->type->getScope() . '-bright')); + $filterInput->setOnKeyPress("SubmitForm('apply_filter', event);"); + $filterElements[] = $filterInput; + } + else { + $filterElements[] = new htmlOutputText(''); + } + } + return $filterElements; + } + /** * Prints the attribute and filter row at the account table head */ @@ -981,7 +1078,7 @@ class lamList { } // get sort order if (isset($_GET['sortdirection'])) { - $this->sortDirection = $_GET['sortdirection']; + $this->sortDirection = htmlspecialchars($_GET['sortdirection']); } // check search suffix if (isset($_POST['suffix'])) { diff --git a/lam/style/responsive/120_lam.css b/lam/style/responsive/120_lam.css index cac4b3f8..5c207838 100644 --- a/lam/style/responsive/120_lam.css +++ b/lam/style/responsive/120_lam.css @@ -78,11 +78,15 @@ table.responsive-table { margin-top: 1rem; table-layout: fixed; width: 100%; + border-collapse: collapse; } table.responsive-table th { text-align: left; - padding: 0; + padding-bottom: 0.5rem; + padding-top: 0.5rem; + padding-right: 0.3rem; + padding-left: 0.3rem; } table.responsive-table td { @@ -90,8 +94,8 @@ table.responsive-table td { vertical-align: top; padding-bottom: 0.5rem; padding-top: 0.5rem; - padding-right: 0.1rem; - padding-left: 0.1rem; + padding-right: 0.3rem; + padding-left: 0.3rem; word-break: break-all; }