Skip to content

Commit 844cf57

Browse files
authored
Merge pull request #190 from angular-ui/padding-class
Padding class
2 parents 7d649cd + 1a0d168 commit 844cf57

File tree

8 files changed

+190
-201
lines changed

8 files changed

+190
-201
lines changed

src/modules/padding.js

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,36 @@ Object.getOwnPropertyNames(CacheProto.prototype).forEach(methodName =>
4949
Cache.prototype[methodName] = CacheProto.prototype[methodName]
5050
);
5151

52-
export default function Padding(template) {
53-
let result;
54-
52+
function generateElement(template) {
5553
if(template.nodeType !== Node.ELEMENT_NODE) {
5654
throw new Error('ui-scroll directive requires an Element node for templating the view');
5755
}
58-
56+
let element;
5957
switch (template.tagName.toLowerCase()) {
6058
case 'dl':
6159
throw new Error(`ui-scroll directive does not support <${template.tagName}> as a repeating tag: ${template.outerHTML}`);
6260
case 'tr':
6361
let table = angular.element('<table><tr><td><div></div></td></tr></table>');
64-
result = table.find('tr');
62+
element = table.find('tr');
6563
break;
6664
case 'li':
67-
result = angular.element('<li></li>');
65+
element = angular.element('<li></li>');
6866
break;
6967
default:
70-
result = angular.element('<div></div>');
68+
element = angular.element('<div></div>');
7169
}
70+
return element;
71+
}
7272

73-
result.cache = new Cache();
73+
class Padding {
74+
constructor(template) {
75+
this.element = generateElement(template);
76+
this.cache = new Cache();
77+
}
78+
79+
height() {
80+
return this.element.height.apply(this.element, arguments);
81+
}
82+
}
7483

75-
return result;
76-
}
84+
export default Padding;

src/modules/viewport.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,20 @@ export default function Viewport(elementRoutines, buffer, element, viewportContr
2525
createPaddingElements(template) {
2626
topPadding = new Padding(template);
2727
bottomPadding = new Padding(template);
28-
element.before(topPadding);
29-
element.after(bottomPadding);
28+
element.before(topPadding.element);
29+
element.after(bottomPadding.element);
30+
topPadding.height(0);
31+
bottomPadding.height(0);
3032
},
3133

3234
applyContainerStyle() {
33-
if (container && container !== viewport) {
35+
if (!container) {
36+
return true;
37+
}
38+
if(container !== viewport) {
3439
viewport.css('height', window.getComputedStyle(container[0]).height);
3540
}
41+
return viewport.height() > 0;
3642
},
3743

3844
bottomDataPos() {
@@ -54,11 +60,11 @@ export default function Viewport(elementRoutines, buffer, element, viewportContr
5460
},
5561

5662
insertElement(e, sibling) {
57-
return elementRoutines.insertElement(e, sibling || topPadding);
63+
return elementRoutines.insertElement(e, sibling || topPadding.element);
5864
},
5965

6066
insertElementAnimated(e, sibling) {
61-
return elementRoutines.insertElementAnimated(e, sibling || topPadding);
67+
return elementRoutines.insertElementAnimated(e, sibling || topPadding.element);
6268
},
6369

6470
shouldLoadBottom() {

src/ui-scroll.js

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,10 @@ angular.module('ui.scroll', [])
3939
'$injector',
4040
'$rootScope',
4141
'$timeout',
42+
'$interval',
4243
'$q',
4344
'$parse',
44-
function (console, $injector, $rootScope, $timeout, $q, $parse) {
45+
function (console, $injector, $rootScope, $timeout, $interval, $q, $parse) {
4546

4647
return {
4748
require: ['?^uiScrollViewport'],
@@ -59,14 +60,16 @@ angular.module('ui.scroll', [])
5960
}
6061

6162
function parseNumericAttr(value, defaultValue) {
62-
let result = $parse(value)($scope);
63+
const result = $parse(value)($scope);
6364
return isNaN(result) ? defaultValue : result;
6465
}
6566

6667
const BUFFER_MIN = 3;
6768
const BUFFER_DEFAULT = 10;
6869
const PADDING_MIN = 0.3;
6970
const PADDING_DEFAULT = 0.5;
71+
const MAX_VIEWPORT_DELAY = 500;
72+
const VIEWPORT_POLLING_INTERVAL = 50;
7073

7174
let datasource = null;
7275
const itemName = match[1];
@@ -78,16 +81,16 @@ angular.module('ui.scroll', [])
7881
let ridActual = 0;// current data revision id
7982
let pending = [];
8083

81-
let elementRoutines = new ElementRoutines($injector, $q);
82-
let buffer = new ScrollBuffer(elementRoutines, bufferSize);
83-
let viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding);
84-
let adapter = new Adapter(viewport, buffer, adjustBuffer, reload, $attr, $parse, $scope);
84+
const elementRoutines = new ElementRoutines($injector, $q);
85+
const buffer = new ScrollBuffer(elementRoutines, bufferSize);
86+
const viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding);
87+
const adapter = new Adapter(viewport, buffer, adjustBuffer, reload, $attr, $parse, $scope);
8588

8689
if (viewportController) {
8790
viewportController.adapter = adapter;
8891
}
8992

90-
let isDatasourceValid = () => angular.isObject(datasource) && angular.isFunction(datasource.get);
93+
const isDatasourceValid = () => angular.isObject(datasource) && angular.isFunction(datasource.get);
9194
datasource = $parse(datasourceName)($scope); // try to get datasource on scope
9295
if (!isDatasourceValid()) {
9396
datasource = $injector.get(datasourceName); // try to inject datasource as service
@@ -114,7 +117,7 @@ angular.module('ui.scroll', [])
114117
}
115118

116119
function defineIndexProperty(datasource, propName, propUserName) {
117-
let descriptor = Object.getOwnPropertyDescriptor(datasource, propName);
120+
const descriptor = Object.getOwnPropertyDescriptor(datasource, propName);
118121
if (descriptor && (descriptor.set || descriptor.get)) {
119122
return;
120123
}
@@ -124,7 +127,7 @@ angular.module('ui.scroll', [])
124127
set: (value) => {
125128
getter = value;
126129
buffer[propUserName] = value;
127-
let topPaddingHeightOld = viewport.topDataPos();
130+
const topPaddingHeightOld = viewport.topDataPos();
128131
viewport.adjustPaddings();
129132
if (propName === 'minIndex') {
130133
viewport.onAfterMinIndexSet(topPaddingHeightOld);
@@ -157,6 +160,26 @@ angular.module('ui.scroll', [])
157160
}, success);
158161
};
159162

163+
const run = () => {
164+
let tryCount = 0;
165+
if(!viewport.applyContainerStyle()) {
166+
const timer = $interval(() => {
167+
tryCount++;
168+
if(viewport.applyContainerStyle()) {
169+
$interval.cancel(timer);
170+
reload();
171+
}
172+
if(tryCount * VIEWPORT_POLLING_INTERVAL >= MAX_VIEWPORT_DELAY) {
173+
$interval.cancel(timer);
174+
throw Error(`ui-scroll directive requires a viewport with non-zero height in ${MAX_VIEWPORT_DELAY}ms`);
175+
}
176+
}, VIEWPORT_POLLING_INTERVAL);
177+
}
178+
else {
179+
reload();
180+
}
181+
};
182+
160183
/**
161184
* Build padding elements
162185
*
@@ -180,10 +203,7 @@ angular.module('ui.scroll', [])
180203

181204
viewport.bind('mousewheel', wheelHandler);
182205

183-
$timeout(() => {
184-
viewport.applyContainerStyle();
185-
reload();
186-
});
206+
run();
187207

188208
/* Private function definitions */
189209

@@ -239,7 +259,7 @@ angular.module('ui.scroll', [])
239259

240260
function createElement(wrapper, insertAfter, insertElement) {
241261
let promises = null;
242-
let sibling = (insertAfter > 0) ? buffer[insertAfter - 1].element : undefined;
262+
const sibling = (insertAfter > 0) ? buffer[insertAfter - 1].element : undefined;
243263
linker((clone, scope) => {
244264
promises = insertElement(clone, sibling);
245265
wrapper.element = clone;
@@ -248,7 +268,7 @@ angular.module('ui.scroll', [])
248268
});
249269
// ui-scroll-grid apply
250270
if (adapter.transform) {
251-
let tdInitializer = wrapper.scope.uiScrollTdInitializer;
271+
const tdInitializer = wrapper.scope.uiScrollTdInitializer;
252272
if (tdInitializer && tdInitializer.linking) {
253273
adapter.transform(wrapper.scope, wrapper.element);
254274
} else {
@@ -459,8 +479,8 @@ angular.module('ui.scroll', [])
459479

460480
function wheelHandler(event) {
461481
if (!adapter.disabled) {
462-
let scrollTop = viewport[0].scrollTop;
463-
let yMax = viewport[0].scrollHeight - viewport[0].clientHeight;
482+
const scrollTop = viewport[0].scrollTop;
483+
const yMax = viewport[0].scrollHeight - viewport[0].clientHeight;
464484

465485
if ((scrollTop === 0 && !buffer.bof) || (scrollTop === yMax && !buffer.eof)) {
466486
event.preventDefault();

test/AssigningSpec.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,13 @@ describe('uiScroll', function () {
4040
};
4141

4242
var executeTest = function(template, scopeSelector, scopeContainer) {
43-
inject(function($rootScope, $compile, $timeout) {
43+
inject(function($rootScope, $compile) {
4444
// build and render
4545
var templateElement = angular.element(template);
4646
var scope = $rootScope.$new();
4747
angular.element(document).find('body').append(templateElement);
4848
$compile(templateElement)(scope);
4949
scope.$apply();
50-
$timeout.flush();
5150

5251
// find adapter element and scope container
5352
var adapterContainer;

0 commit comments

Comments
 (0)