ManifestWebDesign / angular-gridster

An implementation of gridster-like widgets for Angular JS
http://manifestwebdesign.github.io/angular-gridster/
MIT License
964 stars 394 forks source link

Grid height activating scroll intermittently #301

Open dcustodio opened 9 years ago

dcustodio commented 9 years ago

Hi there! I've run across a possible bug that happens when the grid heigh is on the threshold that the browser defines for showing/hiding the scrollbar: intermittently scroll

I have colWidth is set to 'auto' and rowHeight is 'match'.

This happens when for example the grid has four rows, but if it had a fifth the grid height it would be on the browser scrollbar overflow threshold.

It seems there are two watches that are triggering other's, always updating their size. as a workaround I commented the line

function updateHeight() {
    $elem.css('height', (gridster.gridHeight * gridster.curRowHeight) + (gridster.outerMargin ? gridster.margins[0] : -gridster.margins[0]) + 'px');
}

This workaround is not great because then the grid has no real heigh...

andrey-skl commented 9 years ago

I have same issue, please fix.

andrey-skl commented 9 years ago

The better workaround (or solution?) is dropping debounce from resize listeners:

                        var onResize = function onResize() {
                            resize();
                            $timeout(function() {
                                scope.$apply();
                            });
                        };
andrey-skl commented 9 years ago

Sorry, that workaround works only with angular-gridster@0.13.2

andrey-skl commented 9 years ago

When I'm trying to reproduce that issue on 0.13.3, I also got [$rootScope:infdig] 10 $digest() iterations reached. Aborting! Watchers fired in the last 5 iterations: [[{"msg":"fn: function () {\n\t\t\t\t\t\t\t\treturn $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\t\t\t\t\t\t\t}","newVal":1133,"oldVal":1118},{"msg":"fn: function () {\n return element.offsetWidth || parseInt(element.style.width, 10);\n }","newVal":1118,"oldVal":1133}],[{"msg":"fn: function () {\n\t\t\t\t\t\t\t\treturn $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\t\t\t\t\t\t\t}","newVal":1118,"oldVal":1133},{"msg":"fn: function () {\n return element.offsetWidth || parseInt(element.style.width, 10);\n }","newVal":1133,"oldVal":1118}],[{"msg":"fn: function () {\n\t\t\t\t\t\t\t\treturn $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\t\t\t\t\t\t\t}","newVal":1133,"oldVal":1118},{"msg":"fn: function () {\n return element.offsetWidth || parseInt(element.style.width, 10);\n }","newVal":1118,"oldVal":1133}],[{"msg":"fn: function () {\n\t\t\t\t\t\t\t\treturn $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\t\t\t\t\t\t\t}","newVal":1118,"oldVal":1133},{"msg":"fn: function () {\n return element.offsetWidth || parseInt(element.style.width, 10);\n }","newVal":1133,"oldVal":1118}],[{"msg":"fn: function () {\n\t\t\t\t\t\t\t\treturn $elem[0].offsetWidth || parseInt($elem.css('width'), 10);\n\t\t\t\t\t\t\t}","newVal":1133,"oldVal":1118},{"msg":"fn: function () {\n return element.offsetWidth || parseInt(element.style.width, 10);\n }","newVal":1118,"oldVal":1133}]]

dcustodio commented 9 years ago

commit 8dbca649d8282df5ca4fb410f9d0428b1e027e33 seems to resolve this issue. Thanks!

andrey-skl commented 9 years ago

You can also try to use javascriprt-detect-element-resize module

jakepens71 commented 8 years ago

Using gridster 13.5 and making the changes that correspond to https://github.com/ManifestWebDesign/angular-gridster/commit/8dbca649d8282df5ca4fb410f9d0428b1e027e33 seem to make the grid objects now pulse rather rapidly however the effect is still the same.

I have also tried downloading his source code for it directly (https://github.com/ManifestWebDesign/angular-gridster/tree/8dbca649d8282df5ca4fb410f9d0428b1e027e33). However, the effect is still the same. Any ideas?

andrey-skl commented 8 years ago

So I have researched a workaround for that. The main Idea is reducing my app container right margin with scroll width when it appears. So scroll appearing doesnt change actual document height and gridster doesnt goes to this infinite loop of resizing.

There is a directive for scrollbar width detecting I'm using. So I created a directive which reacts on gridster resizes and add/remove margin shift if needed.

import scrollbarWidth from 'scrollbar-width';

...
  .directive('dshGridScrollCompensator', function () {
    return {
      restrict: 'A',
      link: function (scope, iElement) {
        var element = iElement[0];
        var scrollWidth = scrollbarWidth();
        var defaultMarginRight = window.getComputedStyle(element).marginRight;
        console.log('scroll bar width', scrollWidth);

        scope.$on('gridster-resized', () => {
          var hasOverflow = document.body.offsetHeight < document.body.scrollHeight;

          if (hasOverflow) {
            var compensatedMargin = parseInt(defaultMarginRight) - scrollWidth;
            element.style.marginRight = compensatedMargin + 'px';
          } else {
            element.style.marginRight = defaultMarginRight;
          }
        });
      }
    };
  });

I applied this directive on my application container div which has margins 32px by default. So now when scroll appears it reduces to 17px.

Tested on latest master (ManifestWebDesign/angular-gridster#281de99) but should work on any version.

andrewjb123 commented 7 years ago

as a temporary work around i simply applied:

overflow-y: scroll

to the grid - this makes the y scroll bar appear always, which stops the scroll bar showing and hiding which affects the alignment of the tiles.

not ideal as the y scroll always shows, but it solved a headache for me