Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 0dd316e

Browse files
feat(jqLite): add private jqDocumentComplete function
This helper function can be used to execute a callback only after the document has completed its loading, i.e. after the `load` event fires or immediately if the page has already loaded and `document.readyState === 'complete'`.
1 parent b6f4d4b commit 0dd316e

File tree

4 files changed

+61
-0
lines changed

4 files changed

+61
-0
lines changed

src/.jshintrc

+1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
"addEventListenerFn": false,
141141
"removeEventListenerFn": false,
142142
"jqLiteIsTextNode": false,
143+
"jqLiteDocumentLoaded": false,
143144

144145
/* apis.js */
145146
"hashKey": false,

src/jqLite.js

+14
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,20 @@ function jqLiteRemove(element, keepData) {
453453
if (parent) parent.removeChild(element);
454454
}
455455

456+
457+
function jqLiteDocumentLoaded(action, win) {
458+
win = win || window;
459+
if (win.document.readyState === 'complete') {
460+
// Force the action to be run async for consistent behaviour
461+
// from the action's point of view
462+
// i.e. it will definitely not be in a $apply
463+
win.setTimeout(action);
464+
} else {
465+
// No need to unbind this handler as load is only ever called once
466+
jqLite(win).on('load', action);
467+
}
468+
}
469+
456470
//////////////////////////////////////////
457471
// Functions which are declared directly.
458472
//////////////////////////////////////////

test/.jshintrc

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
"JQLitePrototype": false,
120120
"addEventListenerFn": false,
121121
"removeEventListenerFn": false,
122+
"jqLiteDocumentLoaded": false,
122123

123124
/* apis.js */
124125
"hashKey": false,

test/jqLiteSpec.js

+45
Original file line numberDiff line numberDiff line change
@@ -1993,4 +1993,49 @@ describe('jqLite', function() {
19931993
});
19941994
});
19951995

1996+
1997+
describe('jqLiteDocumentLoaded', function() {
1998+
1999+
function createMockWindow(readyState) {
2000+
return {
2001+
document: {readyState: readyState || 'loading'},
2002+
setTimeout: jasmine.createSpy('window.setTimeout'),
2003+
addEventListener: jasmine.createSpy('window.addEventListener'),
2004+
removeEventListener: jasmine.createSpy('window.removeEventListener')
2005+
};
2006+
}
2007+
2008+
it('should execute the callback via a timeout if the document has already completed loading', function() {
2009+
function onLoadCallback() { }
2010+
2011+
var mockWindow = createMockWindow('complete');
2012+
2013+
jqLiteDocumentLoaded(onLoadCallback, mockWindow);
2014+
2015+
expect(mockWindow.addEventListener).not.toHaveBeenCalled();
2016+
expect(mockWindow.setTimeout.mostRecentCall.args[0]).toBe(onLoadCallback);
2017+
});
2018+
2019+
2020+
it('should register a listener for the `load` event', function() {
2021+
var onLoadCallback = jasmine.createSpy('onLoadCallback');
2022+
var mockWindow = createMockWindow();
2023+
2024+
jqLiteDocumentLoaded(onLoadCallback, mockWindow);
2025+
2026+
expect(mockWindow.addEventListener).toHaveBeenCalledOnce();
2027+
});
2028+
2029+
2030+
it('should execute the callback only once the document completes loading', function() {
2031+
var onLoadCallback = jasmine.createSpy('onLoadCallback');
2032+
var mockWindow = createMockWindow();
2033+
2034+
jqLiteDocumentLoaded(onLoadCallback, mockWindow);
2035+
expect(onLoadCallback).not.toHaveBeenCalled();
2036+
2037+
jqLite(mockWindow).triggerHandler('load');
2038+
expect(onLoadCallback).toHaveBeenCalledOnce();
2039+
});
2040+
});
19962041
});

0 commit comments

Comments
 (0)