From c3847be39f0846de7252ab4be8bbda9e53750ce7 Mon Sep 17 00:00:00 2001
From: Tira + Joao <aodhner+jpereira@pivotal.io>
Date: Tue, 14 Mar 2017 17:27:04 -0400
Subject: [PATCH 04/11] Deselect rows when clicking on column header

---
 web/pgadmin/static/js/selection/column_selector.js | 135 ++++++++++++---------
 .../javascript/selection/column_selector_spec.js   |  32 ++++-
 2 files changed, 109 insertions(+), 58 deletions(-)

diff --git a/web/pgadmin/static/js/selection/column_selector.js b/web/pgadmin/static/js/selection/column_selector.js
index e102ae5a..451625e3 100644
--- a/web/pgadmin/static/js/selection/column_selector.js
+++ b/web/pgadmin/static/js/selection/column_selector.js
@@ -1,70 +1,95 @@
 define(['jquery', 'slickgrid'], function ($) {
-  var ColumnSelector = function (columnDefinitions) {
-    var Slick = window.Slick;
+    var ColumnSelector = function (columnDefinitions) {
+        var Slick = window.Slick;
 
-    var init = function (grid) {
-      grid.onHeaderClick.subscribe(function (e, eventArgument) {
-        var column = eventArgument.column;
-        var _grid = eventArgument.grid;
+        var init = function (grid) {
+            grid.onHeaderClick.subscribe(function (e, eventArgument) {
+                var column = eventArgument.column;
 
-        updateRanges(_grid, column);
+                updateRanges(grid, column.id);
 
-        if(!clickedCheckbox(e)) {
-          var $checkbox = $("[data-id='checkbox-" + column.id + "']");
-          toggleCheckbox($checkbox);
-        }
-      });
-    };
+                if (!clickedCheckbox(e)) {
+                    var $checkbox = $("[data-id='checkbox-" + column.id + "']");
+                    toggleCheckbox($checkbox);
+                }
+            });
+        };
 
-    function updateRanges(_grid, column) {
-      var selectionModel = _grid.getSelectionModel();
-      var ranges = selectionModel.getSelectedRanges();
+        function updateRanges(grid, columnId) {
+            var selectionModel = grid.getSelectionModel();
+            var ranges = selectionModel.getSelectedRanges();
 
-      var columnIndex = _grid.getColumnIndex(column.id);
+            var columnIndex = grid.getColumnIndex(columnId);
 
-      var filteredRanges = ranges.filter(function (range) {
-        return !range.contains(0, columnIndex);
-      });
+            var columnRange = new Slick.Range(0, columnIndex, grid.getDataLength() - 1, columnIndex);
+            var newRanges;
+            if (isColumnSelected(ranges, columnRange)) {
+                newRanges = removeColumn(ranges, columnRange);
+            } else {
+                if (!allRangesAreColumns(ranges, grid)) {
+                    newRanges = [columnRange];
+                } else {
+                    newRanges = addColumn(ranges, columnRange);
+                }
+            }
+            selectionModel.setSelectedRanges(newRanges);
+        }
 
-      if (isNotPreviouslySelectedColumn(filteredRanges, ranges)) {
-        var range = new Slick.Range(0, columnIndex, _grid.getDataLength() - 1, columnIndex);
-        filteredRanges.push(range);
-      }
+        var isColumnSelected = function (ranges, columnRange) {
+            return _.any(ranges, function (range) {
+                return isSameRange(range, columnRange)
+            })
+        };
 
-      selectionModel.setSelectedRanges(filteredRanges);
-    }
+        var isSameRange = function (range, otherRange) {
+            return range.fromCell == otherRange.fromCell && range.toCell == otherRange.toCell &&
+                range.fromRow == otherRange.fromRow && range.toRow == otherRange.toRow;
+        };
 
-    function clickedCheckbox(e) {
-      return e.target.type == "checkbox"
-    }
+        var removeColumn = function (ranges, columnRange) {
+            return _.filter(ranges, function (range) {
+                return !(isSameRange(range, columnRange))
+            })
+        };
+        var addColumn = function (ranges, column) {
+            ranges.push(column);
+            return ranges;
+        };
 
-    function isNotPreviouslySelectedColumn(filteredRanges, ranges) {
-      return filteredRanges.length == ranges.length
-    }
+        var allRangesAreColumns = function (ranges, grid) {
+            return _.every(ranges, function (range) {
+                return range.fromCell == range.toCell &&
+                range.fromRow == 0 && range.toRow == grid.getDataLength() - 1
+            })
+        };
 
-    function toggleCheckbox(checkbox) {
-      if (checkbox.prop("checked")) {
-        checkbox.prop("checked", false)
-      } else {
-        checkbox.prop("checked", true)
-      }
-    }
+        var clickedCheckbox = function (e) {
+            return e.target.type == "checkbox"
+        };
 
-    function getColumnsWithCheckboxes() {
-      return _.map(columnDefinitions, function (columnDefinition) {
-        var name = columnDefinition.name;
-        if(columnDefinition.id != "_checkbox_selector")
-          name = "<div data-test='output-column-header'><input data-id='checkbox-" + columnDefinition.id + "' type='checkbox'>" + columnDefinition.name + "</div>";
-        return _.extend(columnDefinition, {
-          name: name
-        });
-      });
-    }
+        var toggleCheckbox = function (checkbox) {
+            if (checkbox.prop("checked")) {
+                checkbox.prop("checked", false)
+            } else {
+                checkbox.prop("checked", true)
+            }
+        };
 
-    $.extend(this, {
-      "init": init,
-      "getColumnsWithCheckboxes": getColumnsWithCheckboxes
-    });
-  };
-  return ColumnSelector;
+        var getColumnsWithCheckboxes = function () {
+            return _.map(columnDefinitions, function (columnDefinition) {
+                var name = columnDefinition.name;
+                if (columnDefinition.id != "_checkbox_selector")
+                    name = "<div data-test='output-column-header'><input data-id='checkbox-" + columnDefinition.id + "' type='checkbox'> " + columnDefinition.name + "</div>";
+                return _.extend(columnDefinition, {
+                    name: name
+                });
+            });
+        };
+
+        $.extend(this, {
+            "init": init,
+            "getColumnsWithCheckboxes": getColumnsWithCheckboxes
+        });
+    };
+    return ColumnSelector;
 });
diff --git a/web/regression/javascript/selection/column_selector_spec.js b/web/regression/javascript/selection/column_selector_spec.js
index 15b34601..5c0e1c1f 100644
--- a/web/regression/javascript/selection/column_selector_spec.js
+++ b/web/regression/javascript/selection/column_selector_spec.js
@@ -64,8 +64,8 @@ define(
         grid.registerPlugin(columnSelector);
         grid.invalidate();
 
-        expect($(container.find('.slick-header-columns .slick-column-name')[0]).text()).toBe('some-column-name');
-        expect($(container.find('.slick-header-columns .slick-column-name')[1]).text()).toBe('second column');
+        expect($(container.find('.slick-header-columns .slick-column-name')[0]).text()).toBe(' some-column-name');
+        expect($(container.find('.slick-header-columns .slick-column-name')[1]).text()).toBe(' second column');
       });
 
       it("preserves the other attributes of column definitions", function () {
@@ -92,7 +92,6 @@ define(
           grid.registerPlugin(columnSelector);
           grid.invalidate();
           $("body").append(container);
-          container.find('.slick-header-column')[1].click();
         });
 
         afterEach(function () {
@@ -100,6 +99,7 @@ define(
         });
 
         it("selects the column", function () {
+          container.find('.slick-header-column')[1].click();
           var selectedRanges = rowSelectionModel.getSelectedRanges();
           var column = selectedRanges[0];
 
@@ -111,6 +111,7 @@ define(
         });
 
         it("selects another column", function () {
+          container.find('.slick-header-column')[1].click();
           container.find('.slick-header-column')[0].click();
 
           var selectedRanges = rowSelectionModel.getSelectedRanges();
@@ -127,6 +128,7 @@ define(
         });
 
         it("allows clicking on the checkbox", function () {
+          container.find('.slick-header-column')[1].click();
           container.find('.slick-header-columns input')[1].click();
 
           expect($(container.find('.slick-header-columns input')[1]).is(':checked')).toBeFalsy();
@@ -134,19 +136,43 @@ define(
         });
 
         it("checks the checkbox", function () {
+          container.find('.slick-header-column')[1].click();
           expect($(container.find('.slick-header-columns input')[1]).is(':checked')).toBeTruthy();
         });
 
+        describe("when a row is selected", function () {
+          beforeEach(function () {
+            var selectedRanges = [new Slick.Range(0, 0, 0, 1)];
+            rowSelectionModel.setSelectedRanges(selectedRanges);
+          });
+
+          it("deselects the row", function () {
+            container.find('.slick-header-column')[1].click();
+            var selectedRanges = rowSelectionModel.getSelectedRanges();
+
+            expect(selectedRanges.length).toBe(1);
+
+            var column = selectedRanges[0];
+
+            expect(column.fromCell).toBe(1);
+            expect(column.toCell).toBe(1);
+            expect(column.fromRow).toBe(0);
+            expect(column.toRow).toBe(9);
+          })
+        });
+
         describe("click a second time", function () {
           beforeEach(function () {
             container.find('.slick-header-column')[1].click();
           });
 
           it("unchecks checkbox", function () {
+            container.find('.slick-header-column')[1].click();
             expect($(container.find('.slick-header-columns input')[1]).is(':checked')).toBeFalsy();
           });
 
           it("unselects the column", function () {
+            container.find('.slick-header-column')[1].click();
             var selectedRanges = rowSelectionModel.getSelectedRanges();
 
             expect(selectedRanges.length).toEqual(0);
-- 
2.12.0

