From 775a5122c98eecd378dcb556a61af4e446b423d1 Mon Sep 17 00:00:00 2001 From: Pierre Goiffon Date: Thu, 2 Aug 2018 14:36:15 +0000 Subject: [PATCH] Selectable lines in tables can now be checked clicking anywhere in the line (previously this could only be done clicking on the checkbox) SVN:trunk[5994] --- application/nicewebpage.class.inc.php | 1 + css/light-grey.css | 13 +++ css/light-grey.scss | 17 ++++ js/jquery.tablesorter.pager.js | 7 +- js/table-selectable-lines.js | 115 ++++++++++++++++++++++++++ 5 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 js/table-selectable-lines.js diff --git a/application/nicewebpage.class.inc.php b/application/nicewebpage.class.inc.php index 63227e88d..60d1229eb 100644 --- a/application/nicewebpage.class.inc.php +++ b/application/nicewebpage.class.inc.php @@ -47,6 +47,7 @@ class NiceWebPage extends WebPage $this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablesorter.js'); $this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablesorter.pager.js'); $this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.tablehover.js'); + $this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/table-selectable-lines.js'); $this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/field_sorter.js'); $this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/datatable.js'); $this->add_linked_script(utils::GetAbsoluteUrlAppRoot().'js/jquery.positionBy.js'); diff --git a/css/light-grey.css b/css/light-grey.css index 2b2534aba..465e5821b 100644 --- a/css/light-grey.css +++ b/css/light-grey.css @@ -92,6 +92,19 @@ table.listResults td .view-image img { margin-left: auto; margin-right: auto; } +table.listResults > tbody > tr.selected > * { + background-color: #ea7d1e; +} +table.listResults > tbody > tr > * { + transition: background-color 400ms linear; +} +table.listResults > tbody > tr:hover > * { + cursor: pointer; +} +table.listResults > tbody > tr.selected:hover > * { + /* hover on lines is currently done toggling td.hover, and having a rule for links */ + background-color: #f3b37b; +} .edit-image .view-image { display: inline-block; } diff --git a/css/light-grey.scss b/css/light-grey.scss index 8af9db34a..00fb6f8da 100644 --- a/css/light-grey.scss +++ b/css/light-grey.scss @@ -116,6 +116,23 @@ table.listResults td .view-image { } } +table.listResults > tbody > tr.selected > * { + background-color: $combodo-orange; +} + +table.listResults > tbody > tr > * { + transition: background-color 400ms linear; +} + +table.listResults > tbody > tr:hover > * { + cursor: pointer; +} + +table.listResults > tbody > tr.selected:hover > * { + /* hover on lines is currently done toggling td.hover, and having a rule for links */ + background-color: lighten($combodo-orange, 20%); +} + .edit-image { .view-image { display: inline-block; diff --git a/js/jquery.tablesorter.pager.js b/js/jquery.tablesorter.pager.js index b5b02be59..faa975112 100644 --- a/js/jquery.tablesorter.pager.js +++ b/js/jquery.tablesorter.pager.js @@ -90,7 +90,12 @@ function sprintf(format, etc) { function checkAll(table, pager, value) { // Mark all the displayed items as check or unchecked depending on the value - $(table).find(':checkbox[name^=selectObj]').prop('checked', value); + $(table).find(':checkbox[name^=selectObj]').each(function (index, element) { + var $currentCheckbox = $(this); + $currentCheckbox.prop('checked', value); + $currentLine = $currentCheckbox.closest("tr"); + (value) ? $currentLine.addClass("selected") : $currentLine.removeClass("selected"); + }); // Set the 'selectionMode' for the future objects to load if (value) { diff --git a/js/table-selectable-lines.js b/js/table-selectable-lines.js new file mode 100644 index 000000000..ad64d9f4f --- /dev/null +++ b/js/table-selectable-lines.js @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2010-2018 Combodo SARL + * + * This file is part of iTop. + * + * iTop is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * iTop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with iTop. If not, see + * + */ + +$(document).ready(function () { + var SELECTED_CLASS = "selected"; + var TABLE_SELECTOR = 'table.listResults'; + + // we want to select :radio and :checkbox, but there is no :is() selector, so we're using existing :not() + // not ideal but I don't have a better idea for now :/ + var INPUT_SELECTOR = 'input:not([type=image],[type=button],[type=submit])'; + + var FIRST_CELL_WITH_INPUT_SELECTOR = 'td:first-child>'+INPUT_SELECTOR; + var LINE_WITH_INPUT_IN_FIRST_CELL_SELECTOR = "tbody>tr>"+FIRST_CELL_WITH_INPUT_SELECTOR; + var CELLS_WITH_INPUT_SELECTOR = 'td>'+INPUT_SELECTOR; + var LINE_WITH_INPUTS_SELECTOR = "tbody>tr>"+CELLS_WITH_INPUT_SELECTOR; + + + // Tables with inputs inside cells + $(document).on('click', TABLE_SELECTOR+':has('+LINE_WITH_INPUTS_SELECTOR+')', function (event) { + var $eventTarget = $(event.target); + if (shouldExitHandler($eventTarget)) { + return; + } + + var $cellClicked = $eventTarget.closest("td"); + var $cellClickedInput = $cellClicked.find(INPUT_SELECTOR); + if ($cellClickedInput.length === 1) { + $cellClickedInput.click(); + } + }); + + + // Tables with one input in the first cell to select lines + $(document).on('click', TABLE_SELECTOR+':has('+LINE_WITH_INPUT_IN_FIRST_CELL_SELECTOR+')', function (event) { + var $eventTarget = $(event.target); + if (shouldExitHandler($eventTarget)) { + return; + } + + var $lineClicked = $eventTarget.closest("tr"); + var $lineClickedInput = $lineClicked.find(FIRST_CELL_WITH_INPUT_SELECTOR); + $lineClickedInput.click(); + }); + + $(document).on('change', TABLE_SELECTOR+':has('+LINE_WITH_INPUT_IN_FIRST_CELL_SELECTOR+')', function (event) { + var $eventTarget = $(event.target); + if (!$eventTarget.is(INPUT_SELECTOR)) { + return; + } + + updateLines($eventTarget); + }); + + // check_all event is fired for tableSorter JQuery plugin + $(document).on("check_all", TABLE_SELECTOR+':has('+LINE_WITH_INPUT_IN_FIRST_CELL_SELECTOR+')', function () { + $(this).find("tbody>tr").addClass(SELECTED_CLASS); + }); + + // update when clicking on the header checkbox/radio input is handled in tablesorterPager ! + + + /** + * Our custom handlers chould run only if clicking on somewhere without event already attached ! + * @param $eventTarget + * @returns {boolean} true if our custom handler shouldn't be run + */ + function shouldExitHandler($eventTarget) { + if ($eventTarget.is("a, button")) { + return true; + } + if ($eventTarget.parent().is('a, button')) { + return true; + } + if ($eventTarget.is("input, select, option")) { + return true; + } + if ($eventTarget.is("img")) { // too hard to determine if an event handler is attached so excluding all ! + return true; + } + + return false; + } + + + function updateLines($inputChanged) { + var $selectedLine = $inputChanged.closest("tr"); + + if ($inputChanged.is('input:radio')) { + // didn't find a proper event fired when radio is deselected... so doing this ! + $selectedLine + .closest('table') + .find('tr') + .removeClass(SELECTED_CLASS); + } + + $selectedLine.toggleClass(SELECTED_CLASS); + } +});