Skip to content

Commit 8ad2915

Browse files
committed
Merge pull request #57 from aantipov/fix-padding-default-min-values
Fix padding default and min values
2 parents 4039dbe + ab38ddf commit 8ad2915

File tree

3 files changed

+103
-85
lines changed

3 files changed

+103
-85
lines changed

src/ui-scroll.js

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -197,28 +197,9 @@ angular.module('ui.scroll', [])
197197
return buffer;
198198
}
199199

200-
function Padding(template) {
201-
let result;
202-
let tagName = template.localName;
203-
204-
switch (tagName) {
205-
case 'dl':
206-
throw new Error(`ui-scroll directive does not support <${tagName}> as a repeating tag: ${template.outerHTML}`);
207-
case 'tr':
208-
let table = angular.element('<table><tr><td><div></div></td></tr></table>');
209-
result = table.find('tr');
210-
break;
211-
case 'li':
212-
result = angular.element('<li></li>');
213-
break;
214-
default:
215-
result = angular.element('<div></div>');
216-
}
217-
218-
return result;
219-
}
220-
221200
function Viewport(buffer, element, controllers, attrs) {
201+
const PADDING_MIN = 0.3;
202+
const PADDING_DEFAULT = 0.5;
222203
let topPadding = null;
223204
let bottomPadding = null;
224205
let averageItemHeight = 0;
@@ -232,7 +213,7 @@ angular.module('ui.scroll', [])
232213
let viewportOffset = viewport.offset() ? () => viewport.offset() : () => ({top: 0});
233214

234215
function bufferPadding() {
235-
return viewport.outerHeight() * Math.max(0.1, +attrs.padding || 0.1); // some extra space to initiate preload
216+
return viewport.outerHeight() * Math.max(PADDING_MIN, +attrs.padding || PADDING_DEFAULT); // some extra space to initiate preload
236217
}
237218

238219
angular.extend(viewport, {
@@ -241,6 +222,27 @@ angular.module('ui.scroll', [])
241222
bottomPadding = new Padding(template);
242223
element.before(topPadding);
243224
element.after(bottomPadding);
225+
226+
function Padding(template) {
227+
let result;
228+
let tagName = template.localName;
229+
230+
switch (tagName) {
231+
case 'dl':
232+
throw new Error(`ui-scroll directive does not support <${tagName}> as a repeating tag: ${template.outerHTML}`);
233+
case 'tr':
234+
let table = angular.element('<table><tr><td><div></div></td></tr></table>');
235+
result = table.find('tr');
236+
break;
237+
case 'li':
238+
result = angular.element('<li></li>');
239+
break;
240+
default:
241+
result = angular.element('<div></div>');
242+
}
243+
244+
return result;
245+
}
244246
},
245247

246248
bottomDataPos() {
@@ -278,7 +280,7 @@ angular.module('ui.scroll', [])
278280
// clip the invisible items off the bottom
279281
let overage = 0;
280282

281-
for(let i = buffer.length - 1; i >= 0; i--) {
283+
for (let i = buffer.length - 1; i >= 0; i--) {
282284
if (buffer[i].element.offset().top - viewportOffset().top <= viewport.outerHeight() + bufferPadding()) {
283285
break;
284286
}
@@ -302,8 +304,8 @@ angular.module('ui.scroll', [])
302304
let overage = 0;
303305
let overageHeight = 0;
304306

305-
for(let i = 0; i < buffer.length; i++) {
306-
if(buffer[i].element.offset().top - viewportOffset().top + buffer[i].element.outerHeight(true) >= (-1) * bufferPadding()) {
307+
for (let i = 0; i < buffer.length; i++) {
308+
if (buffer[i].element.offset().top - viewportOffset().top + buffer[i].element.outerHeight(true) >= (-1) * bufferPadding()) {
307309
break;
308310
}
309311
overageHeight += buffer[i].element.outerHeight(true);
@@ -435,7 +437,7 @@ angular.module('ui.scroll', [])
435437
this.calculateProperties = function () {
436438
let i, item, itemHeight, itemTop, isNewRow, rowTop;
437439
let topHeight = 0;
438-
for(i = 0; i < buffer.length; i++) {
440+
for (i = 0; i < buffer.length; i++) {
439441
item = buffer[i];
440442
itemTop = item.element.offset().top;
441443
isNewRow = rowTop !== itemTop;

test/BasicTestsSpec.js

Lines changed: 73 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -110,54 +110,61 @@ describe('uiScroll', function () {
110110
});
111111

112112
describe('datasource with 20 elements and buffer size 3 - constrained viewport', function () {
113-
var scrollSettings = { datasource: 'myMultipageDatasource', itemHeight: 40, bufferSize: 3 };
113+
var scrollSettings = { datasource: 'myMultipageDatasource', viewportHeight: 200, itemHeight: 40, bufferSize: 3 };
114114

115-
it('should create 6 divs with data (+ 2 padding divs)', function () {
115+
it('should create 9 divs with data (+ 2 padding divs)', function () {
116116
runTest(scrollSettings,
117-
function (viewport) {
118-
expect(viewport.children().length).toBe(8);
119-
expect(viewport.scrollTop()).toBe(0);
120-
expect(viewport.children().css('height')).toBe('0px');
121-
expect(angular.element(viewport.children()[7]).css('height')).toBe('0px');
122-
123-
for (var i = 1; i < 7; i++) {
124-
var row = viewport.children()[i];
125-
expect(row.tagName.toLowerCase()).toBe('div');
126-
expect(row.innerHTML).toBe(i + ': item' + i);
127-
}
117+
function (viewport) {
118+
var itemsLoaded = 9;
119+
var itemsWithPaddings = itemsLoaded + 2;
120+
expect(viewport.children().length).toBe(itemsWithPaddings);
121+
expect(viewport.scrollTop()).toBe(0);
122+
expect(viewport.children().css('height')).toBe('0px');
123+
expect(angular.element(viewport.children()[itemsWithPaddings - 1]).css('height')).toBe('0px');
124+
125+
for (var i = 1; i < itemsLoaded; i++) {
126+
var row = viewport.children()[i];
127+
expect(row.tagName.toLowerCase()).toBe('div');
128+
expect(row.innerHTML).toBe(i + ': item' + i);
128129
}
130+
}
129131
);
130132
});
131133

132-
it('should call get on the datasource 3 times ', function () {
133-
var spy;
134-
inject(function (myMultipageDatasource) {
135-
spy = spyOn(myMultipageDatasource, 'get').and.callThrough();
136-
});
134+
it('should call get on the datasource 4 times ', function () {
135+
var spy;
136+
inject(function (myMultipageDatasource) {
137+
spy = spyOn(myMultipageDatasource, 'get').and.callThrough();
138+
});
137139
runTest(scrollSettings,
138140
function () {
139-
expect(spy.calls.all().length).toBe(3);
141+
// There are 9 loaded items, so there were 3 data calls
142+
// Additional call was for top items resulted with 0 items.
143+
expect(spy.calls.all().length).toBe(4);
140144

141145
expect(spy.calls.all()[0].args[0]).toBe(1);
142146
expect(spy.calls.all()[1].args[0]).toBe(4);
143-
expect(spy.calls.all()[2].args[0]).toBe(-2);
147+
expect(spy.calls.all()[2].args[0]).toBe(7);
148+
expect(spy.calls.all()[3].args[0]).toBe(-2);
144149
}
145150
);
146151
});
147152

148-
it('should create 3 more divs (9 divs total) with data (+ 2 padding divs)', function () {
153+
it('should create 3 more divs (12 divs total) with data (+ 2 padding divs)', function () {
154+
var itemsLoaded = 12;
155+
var itemsWithPaddings = itemsLoaded + 2;
149156
runTest(scrollSettings,
150157
function (viewport) {
151158
viewport.scrollTop(100);
152159
viewport.trigger('scroll');
153160
inject(function ($timeout) {
154161
$timeout.flush();
155-
expect(viewport.children().length).toBe(11);
156-
expect(viewport.scrollTop()).toBe(40);
162+
expect(viewport.children().length).toBe(itemsWithPaddings);
163+
expect(viewport.scrollTop()).toBe(100);
157164
expect(viewport.children().css('height')).toBe('0px');
158-
expect(angular.element(viewport.children()[10]).css('height')).toBe('0px');
165+
expect(angular.element(viewport.children()[itemsWithPaddings-1]).css('height')).toBe('0px');
159166

160-
for (var i = 1; i < 10; i++) {
167+
for (var i = 1; i < itemsLoaded; i++) {
161168
var row = viewport.children()[i];
162169
expect(row.tagName.toLowerCase()).toBe('div');
163170
expect(row.innerHTML).toBe(i + ': item' + i);
@@ -167,7 +174,7 @@ describe('uiScroll', function () {
167174
);
168175
});
169176

170-
it('should call get on the datasource 1 extra time (4 total) ', function () {
177+
it('should call get on the datasource 1 extra time (5 total) ', function () {
171178
var spy;
172179
inject(function (myMultipageDatasource) {
173180
spy = spyOn(myMultipageDatasource, 'get').and.callThrough();
@@ -178,19 +185,23 @@ describe('uiScroll', function () {
178185
viewport.trigger('scroll');
179186
$timeout.flush();
180187

181-
expect(spy.calls.all().length).toBe(4);
188+
expect(spy.calls.all().length).toBe(5);
182189

183190
expect(spy.calls.all()[0].args[0]).toBe(1);
184191
expect(spy.calls.all()[1].args[0]).toBe(4);
185-
expect(spy.calls.all()[2].args[0]).toBe(-2);
186-
expect(spy.calls.all()[3].args[0]).toBe(7);
192+
expect(spy.calls.all()[2].args[0]).toBe(7);
193+
expect(spy.calls.all()[3].args[0]).toBe(-2);
194+
expect(spy.calls.all()[4].args[0]).toBe(10);
187195
}
188196
);
189197
});
190198

191-
it('should clip 3 divs from the top and add 3 more divs to the bottom (9 divs total) (+ 2 padding divs)', function () {
199+
it('should clip 4 divs from the top and add 3 more divs to the bottom (11 divs total) (+ 2 padding divs)', function () {
192200
runTest(scrollSettings,
193201
function (viewport, scope, $timeout) {
202+
var itemsLoaded = 11;
203+
var itemsWithPaddings = itemsLoaded + 2;
204+
var clippedDivs = 4;
194205
viewport.scrollTop(100);
195206
viewport.trigger('scroll');
196207
$timeout.flush();
@@ -199,27 +210,28 @@ describe('uiScroll', function () {
199210
viewport.trigger('scroll');
200211
$timeout.flush();
201212

202-
expect(viewport.children().length).toBe(11);
203-
expect(viewport.scrollTop()).toBe(160);
204-
expect(viewport.children().css('height')).toBe('120px');
205-
expect(angular.element(viewport.children()[10]).css('height')).toBe('0px');
213+
expect(viewport.children().length).toBe(itemsWithPaddings);
214+
expect(viewport.scrollTop()).toBe(280);
215+
expect(viewport.children().css('height')).toBe('160px');
216+
expect(angular.element(viewport.children()[itemsWithPaddings-1]).css('height')).toBe('0px');
206217

207-
for (var i = 1; i < 10; i++) {
218+
for (var i = 1; i <= itemsLoaded; i++) {
208219
var row = viewport.children()[i];
209220
expect(row.tagName.toLowerCase()).toBe('div');
210-
expect(row.innerHTML).toBe((i + 3) + ': item' + (i + 3));
221+
expect(row.innerHTML).toBe((i + clippedDivs) + ': item' + (i + clippedDivs));
211222
}
212223
}
213224
);
214225
});
215226

216-
it('should call get on the datasource 1 more time (4 total) ', function () {
227+
it('should call get on the datasource 1 more time (6 total) ', function () {
217228
var spy;
218229
inject(function (myMultipageDatasource) {
219230
spy = spyOn(myMultipageDatasource, 'get').and.callThrough();
220231
});
221232
runTest(scrollSettings,
222233
function (viewport, scope, $timeout) {
234+
var calls = 6;
223235

224236
viewport.scrollTop(100);
225237
viewport.trigger('scroll');
@@ -229,20 +241,23 @@ describe('uiScroll', function () {
229241
viewport.trigger('scroll');
230242
$timeout.flush();
231243

232-
expect(spy.calls.all().length).toBe(5);
244+
expect(spy.calls.all().length).toBe(calls);
233245
expect(spy.calls.all()[0].args[0]).toBe(1);
234246
expect(spy.calls.all()[1].args[0]).toBe(4);
235-
expect(spy.calls.all()[2].args[0]).toBe(-2);
236-
expect(spy.calls.all()[3].args[0]).toBe(7);
247+
expect(spy.calls.all()[2].args[0]).toBe(7);
248+
expect(spy.calls.all()[3].args[0]).toBe(-2);
237249
expect(spy.calls.all()[4].args[0]).toBe(10);
250+
expect(spy.calls.all()[5].args[0]).toBe(13);
238251
}
239252
);
240253
});
241254

242-
it('should re-add 3 divs at the top and clip 3 divs from the bottom (9 divs total) (+ 2 padding divs)', function () {
255+
it('should re-add 3 divs at the top and clip 2 divs from the bottom (9 divs total) (+ 2 padding divs)', function () {
243256
runTest(scrollSettings,
244257
function (viewport, scope, $timeout) {
245258
var flush = $timeout.flush;
259+
var itemsLoaded = 8;
260+
var itemsWithPaddings = itemsLoaded + 2;
246261

247262
viewport.scrollTop(100);
248263
viewport.trigger('scroll');
@@ -256,12 +271,12 @@ describe('uiScroll', function () {
256271
viewport.trigger('scroll');
257272
flush();
258273

259-
expect(viewport.children().length).toBe(8);
274+
expect(viewport.children().length).toBe(itemsWithPaddings);
260275
expect(viewport.scrollTop()).toBe(0);
261276
expect(viewport.children().css('height')).toBe('0px');
262-
expect(angular.element(viewport.children()[7]).css('height')).toBe('240px');
277+
expect(angular.element(viewport.children()[itemsWithPaddings-1]).css('height')).toBe('280px');
263278

264-
for (var i = 1; i < 7; i++) {
279+
for (var i = 1; i <= itemsLoaded; i++) {
265280
var row = viewport.children()[i];
266281
expect(row.tagName.toLowerCase()).toBe('div');
267282
expect(row.innerHTML).toBe((i) + ': item' + (i));
@@ -270,7 +285,7 @@ describe('uiScroll', function () {
270285
);
271286
});
272287

273-
it('should call get on the datasource 1 more time (4 total) ', function () {
288+
it('should call get on the datasource 1 more time (8 total) ', function () {
274289
var spy;
275290
inject(function (myMultipageDatasource) {
276291
spy = spyOn(myMultipageDatasource, 'get').and.callThrough();
@@ -279,6 +294,7 @@ describe('uiScroll', function () {
279294
runTest(scrollSettings,
280295
function (viewport, scope, $timeout) {
281296
var flush = $timeout.flush;
297+
var totalCallsNumber = 8;
282298

283299
viewport.scrollTop(100);
284300
viewport.trigger('scroll');
@@ -292,15 +308,15 @@ describe('uiScroll', function () {
292308
viewport.trigger('scroll');
293309
flush();
294310

295-
expect(spy.calls.all().length).toBe(7);
311+
expect(spy.calls.all().length).toBe(totalCallsNumber);
296312
expect(spy.calls.all()[0].args[0]).toBe(1);
297313
expect(spy.calls.all()[1].args[0]).toBe(4);
298-
expect(spy.calls.all()[2].args[0]).toBe(-2);
299-
expect(spy.calls.all()[3].args[0]).toBe(7);
314+
expect(spy.calls.all()[2].args[0]).toBe(7);
315+
expect(spy.calls.all()[3].args[0]).toBe(-2);
300316
expect(spy.calls.all()[4].args[0]).toBe(10);
301-
expect(spy.calls.all()[5].args[0]).toBe(1);
302-
expect(spy.calls.all()[6].args[0]).toBe(-2);
303-
317+
expect(spy.calls.all()[5].args[0]).toBe(13);
318+
expect(spy.calls.all()[6].args[0]).toBe(2);
319+
expect(spy.calls.all()[7].args[0]).toBe(-1);
304320
}
305321
);
306322
});
@@ -392,7 +408,7 @@ describe('uiScroll', function () {
392408
expect(spy.calls.all()[0].args[0]).toBe(1);
393409
expect(spy.calls.all()[1].args[0]).toBe(4); //last full
394410
expect(spy.calls.all()[2].args[0]).toBe(-2);
395-
expect(spy.calls.all()[3].args[0]).toBe(5); //empty
411+
expect(spy.calls.all()[3].args[0]).toBe(6); //empty
396412

397413
}
398414
);
@@ -482,25 +498,25 @@ describe('uiScroll', function () {
482498
viewport.trigger('scroll');
483499

484500
wheelEventElement.dispatchEvent(getNewWheelEvent()); //now we are at the top but preventDefault is occurred because of bof will be reached only after next scroll trigger
485-
expect(documentScrollBubblingCount).toBe(1); //here! the only one prevented wheel-event
501+
expect(documentScrollBubblingCount).toBe(2); //here! the only one prevented wheel-event
486502

487503
flush();
488504

489505
wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred but document will not scroll because of viewport will be scrolled
490-
expect(documentScrollBubblingCount).toBe(2);
506+
expect(documentScrollBubblingCount).toBe(3);
491507

492508
viewport.scrollTop(0);
493509
viewport.trigger('scroll'); //bof will be reached right after that
494510

495511
flush();
496512

497513
wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred because of we are at the top and bof is reached
498-
expect(documentScrollBubblingCount).toBe(3);
514+
expect(documentScrollBubblingCount).toBe(4);
499515

500516
expect(flush).toThrow(); //there is no new data, bof is reached
501517

502518
wheelEventElement.dispatchEvent(getNewWheelEvent()); //preventDefault will not occurred because of we are at the top and bof is reached
503-
expect(documentScrollBubblingCount).toBe(4);
519+
expect(documentScrollBubblingCount).toBe(5);
504520

505521
}, {
506522
cleanupTest: function () {
@@ -678,7 +694,7 @@ describe('uiScroll', function () {
678694
}
679695

680696
// unstable delta passing
681-
viewport.scrollTop(viewport.scrollTop() - 5);
697+
viewport.scrollTop(viewport.scrollTop());
682698

683699
// scroll up + expectation
684700
for(i = 0; i < limit; i++) {

test/VisibilitySwitchingSpec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ describe('uiScroll', function () {
1616
describe('viewport visibility changing', function () {
1717
var scrollSettings = { datasource: 'myMultipageDatasource', viewportHeight: 200, itemHeight: 40, bufferSize: 3, adapter: 'adapter' };
1818
var onePackItemsCount = 3 + 2;
19-
var twoPacksItemsCount = 3 * 2 + 2;
19+
var twoPacksItemsCount = 3 * 3 + 2;
2020

21-
it('should create 6 divs with data (+ 2 padding divs)', function () {
21+
it('should create 9 divs with data (+ 2 padding divs)', function () {
2222
runTest(scrollSettings,
2323
function (viewport) {
2424
expect(viewport.children().length).toBe(twoPacksItemsCount);

0 commit comments

Comments
 (0)