Skip to content

Commit ece45dc

Browse files
authored
Merge pull request #679 from fieg/bind-on-load
Bind on load (DOMContentLoaded)
2 parents ba383bc + 273fabd commit ece45dc

File tree

9 files changed

+73
-34
lines changed

9 files changed

+73
-34
lines changed

docs/events.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ ias.once('appended', handler);
2020

2121
## Reference
2222

23+
### ready
24+
25+
This event is triggered when the DOM is ready. Right after this event Infinite Ajax Scroll will bind (unless the [`bind`](./options.md#bind) option is set to `false`).
26+
2327
### binded
2428

2529
This event is triggered when Infinite Ajax Scroll binds to the scroll and resize events of the scroll container. This mostly happens right after the DOM is ready, but this can be configured with the `bind` option.

docs/options.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttp
9595
## bind
9696

9797
**Type:** `boolean`<br>
98-
**Default:** `false`<br>
98+
**Default:** `true`<br>
9999
**Required:** no
100100

101-
By default Infinite Ajax Scroll binds to the scroll and resize events on document ready. If you want manual control over this behaviour you can set this option to `false`. To bind call the [`bind`](methods.md#bind) method.
101+
By default Infinite Ajax Scroll binds to the scroll and resize events on document ready. If you want to have manual control over this behaviour you can set this option to `false`. To bind manually you can call the [`bind`](methods.md#bind) method.
102102

103103
## scrollContainer
104104

src/events.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const LOADED = 'loaded';
88
export const ERROR = 'error';
99
export const LAST = 'last';
1010
export const NEXT = 'next';
11+
export const READY = 'ready';
1112
export const SCROLLED = 'scrolled';
1213
export const RESIZED = 'resized';
1314
export const PAGE = 'page';
@@ -25,6 +26,7 @@ const events = {
2526
ERROR,
2627
LAST,
2728
NEXT,
29+
READY,
2830
SCROLLED,
2931
RESIZED,
3032
PAGE,

src/infinite-ajax-scroll.js

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ export default class InfiniteAjaxScroll {
4646
this.resizeObserver = ResizeObserverFactory(this, this.scrollContainer);
4747
this._scrollListener = throttle(scrollHandler, 200).bind(this);
4848

49+
this.ready = false;
50+
this.bindOnReady = true;
4951
this.binded = false;
5052
this.paused = false;
5153
this.pageIndex = this.sentinel() ? 0 : -1;
@@ -72,9 +74,24 @@ export default class InfiniteAjaxScroll {
7274
// prefill/measure after all plugins are done binding
7375
this.on(Events.BINDED, this.prefill.prefill.bind(this.prefill));
7476

75-
if (this.options.bind) {
76-
// @todo on document.ready? (window.addEventListener('DOMContentLoaded'))
77-
this.bind();
77+
let ready = () => {
78+
if (this.ready) {
79+
return;
80+
}
81+
82+
this.ready = true;
83+
84+
this.emitter.emit(Events.READY);
85+
86+
if (this.bindOnReady && this.options.bind) {
87+
this.bind();
88+
}
89+
};
90+
91+
if (document.readyState === "complete" || document.readyState === "interactive") {
92+
setTimeout(ready, 1);
93+
} else {
94+
window.addEventListener('DOMContentLoaded', ready);
7895
}
7996
}
8097

@@ -83,6 +100,12 @@ export default class InfiniteAjaxScroll {
83100
return;
84101
}
85102

103+
// If we manually call bind before the dom is ready, we assume that we want
104+
// to take control over the bind flow.
105+
if (!this.ready) {
106+
this.bindOnReady = false;
107+
}
108+
86109
this.scrollContainer.addEventListener('scroll', this._scrollListener);
87110
this.resizeObserver.observe();
88111

@@ -93,6 +116,10 @@ export default class InfiniteAjaxScroll {
93116

94117
unbind() {
95118
if (!this.binded) {
119+
if (!this.ready) {
120+
this.once(Events.BINDED, this.unbind);
121+
}
122+
96123
return;
97124
}
98125

@@ -105,6 +132,14 @@ export default class InfiniteAjaxScroll {
105132
}
106133

107134
next() {
135+
if (!this.binded) {
136+
if (!this.ready) {
137+
return this.once(Events.BINDED, this.next);
138+
}
139+
140+
return;
141+
}
142+
108143
this.pause();
109144

110145
let event = {
@@ -169,7 +204,10 @@ export default class InfiniteAjaxScroll {
169204
return;
170205
}
171206

172-
if (xhr.status === 200) {
207+
if (xhr.status === 0) {
208+
// weird status happening during Cypress tests
209+
}
210+
else if (xhr.status === 200) {
173211
let items = xhr.response;
174212

175213
if (responseType === 'document') {
@@ -315,10 +353,13 @@ export default class InfiniteAjaxScroll {
315353
}
316354

317355
once(event, callback) {
318-
this.emitter.once(event, callback, this);
356+
return new Promise((resolve) => {
357+
this.emitter.once(event, function() { Promise.resolve(callback.apply(this, arguments)).then(resolve) }, this);
319358

320-
if (event === Events.BINDED && this.binded) {
321-
callback.bind(this)();
322-
}
359+
if (event === Events.BINDED && this.binded) {
360+
callback.bind(this)();
361+
resolve()
362+
}
363+
})
323364
}
324365
}

test/bind_spec.js

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,7 @@ describe('Bind', () => {
1616

1717
ias.on(events.BINDED, spy.onBind);
1818

19-
cy.get('@spy').should((spy) => {
20-
expect(spy).to.have.been.calledOnce;
21-
});
19+
cy.get('@spy').should('have.been.calledOnce');
2220
});
2321

2422
it('should not bind on instantiation when option.bind is false', () => {
@@ -34,9 +32,7 @@ describe('Bind', () => {
3432

3533
ias.on(events.BINDED, spy.onBind);
3634

37-
cy.get('@spy').should((spy) => {
38-
expect(spy).to.not.have.been.called;
39-
})
35+
cy.get('@spy').should('not.have.been.called')
4036
});
4137

4238
it('should bind manually', () => {
@@ -55,9 +51,7 @@ describe('Bind', () => {
5551

5652
ias.bind();
5753

58-
cy.get('@spy').should((spy) => {
59-
expect(spy).to.have.been.calledOnce;
60-
});
54+
cy.get('@spy').should('have.been.calledOnce');
6155
});
6256

6357
it('should not bind twice', () => {
@@ -77,9 +71,7 @@ describe('Bind', () => {
7771
ias.bind();
7872
ias.bind();
7973

80-
cy.get('@spy').should((spy) => {
81-
expect(spy).to.have.been.calledOnce;
82-
});
74+
cy.get('@spy').should('have.been.calledOnce');
8375
});
8476

8577
it('should unbind', () => {
@@ -98,9 +90,7 @@ describe('Bind', () => {
9890

9991
ias.unbind();
10092

101-
cy.get('@spy').should((spy) => {
102-
expect(spy).to.have.been.calledOnce;
103-
});
93+
cy.get('@spy').should('have.been.calledOnce');
10494
});
10595

10696
it('should not unbind when not binded', () => {
@@ -118,8 +108,6 @@ describe('Bind', () => {
118108

119109
ias.unbind();
120110

121-
cy.get('@spy').should((spy) => {
122-
expect(spy).to.not.have.been.called;
123-
});
111+
cy.get('@spy').should('not.have.been.called');
124112
});
125113
});

test/load_spec.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,9 @@ describe('Load', () => {
7575

7676
ias.on(events.LOADED, spies.loaded);
7777

78-
ias.load('http://localhost:8080/test/fixtures/default/page404.html');
78+
ias.load('http://localhost:8080/test/fixtures/default/page404.html')
79+
.catch((xhr) => {}) // prevent uncaught exception in cypress
80+
;
7981

8082
cy.get('@spy').should('not.have.been.called');
8183
});
@@ -175,8 +177,10 @@ describe('Load', () => {
175177

176178
ias.on(events.ERROR, spies.error);
177179

178-
ias.load('http://localhost:8080/test/fixtures/default/page404.html');
180+
ias.load('http://localhost:8080/test/fixtures/default/page404.html')
181+
.catch((xhr) => {}) // prevent uncaught exception in cypress
182+
;
179183

180-
cy.get('@spy').should('not.have.been.called');
184+
cy.get('@spy').should('have.been.calledOnce');
181185
});
182186
});

test/next_spec.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ describe('Next', () => {
102102
item: '.blocks__block',
103103
next: '.pager__next',
104104
pagination: '.pager',
105-
bind: false
106105
});
107106

108107
ias.next();
@@ -117,13 +116,12 @@ describe('Next', () => {
117116

118117
cy.InfiniteAjaxScroll().then((InfiniteAjaxScroll) => {
119118
cy.window().then((win) => {
120-
const spy = cy.spy(win.console, 'warn').as('consoleSpy');
119+
cy.spy(win.console, 'warn').as('consoleSpy');
121120

122121
let ias = new InfiniteAjaxScroll('.blocks', {
123122
item: '.blocks__block',
124123
next: '.pager__next',
125124
pagination: '.pager',
126-
bind: false
127125
});
128126

129127
ias.next().then(() => { ias.next() });

test/resize_spec.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ describe('Resize', () => {
1111
ias = new InfiniteAjaxScroll('.blocks', {
1212
item: '.blocks__block',
1313
});
14+
ias.bind();
1415
});
1516
});
1617

test/scroll_spec.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ describe('Scroll', () => {
1111
ias = new InfiniteAjaxScroll('.blocks', {
1212
item: '.blocks__block',
1313
});
14+
ias.bind();
1415
});
1516
});
1617

0 commit comments

Comments
 (0)