summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/public/lazyloader.js
blob: 8ca0948cde8558e06401e591864d8ba016217766 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
odoo.define('web.public.lazyloader', function (require) {
'use strict';

var blockEvents = ['submit', 'click'];
var blockFunction = function (ev) {
    ev.preventDefault();
    ev.stopImmediatePropagation();
};

var waitingLazy = false;

/**
 * Blocks the DOM sections which explicitely require the lazy loaded JS to be
 * working (those sections should be marked with the 'o_wait_lazy_js' class).
 *
 * @see stopWaitingLazy
 */
function waitLazy() {
    if (waitingLazy) {
        return;
    }
    waitingLazy = true;

    var lazyEls = document.querySelectorAll('.o_wait_lazy_js');
    for (var i = 0; i < lazyEls.length; i++) {
        var element = lazyEls[i];
        blockEvents.forEach(function (evType) {
            element.addEventListener(evType, blockFunction);
        });
    }
}
/**
 * Unblocks the DOM sections blocked by @see waitLazy and removes the related
 * 'o_wait_lazy_js' class from the whole DOM.
 */
function stopWaitingLazy() {
    if (!waitingLazy) {
        return;
    }
    waitingLazy = false;

    var lazyEls = document.querySelectorAll('.o_wait_lazy_js');
    for (var i = 0; i < lazyEls.length; i++) {
        var element = lazyEls[i];
        blockEvents.forEach(function (evType) {
            element.removeEventListener(evType, blockFunction);
        });
        element.classList.remove('o_wait_lazy_js');
    }
}

// Start waiting for lazy loading as soon as the DOM is available
if (document.readyState !== 'loading') {
    waitLazy();
} else {
    document.addEventListener('DOMContentLoaded', function () {
        waitLazy();
    });
}

// As soon as everything is fully loaded, start loading all the remaining JS
// and unblock the related DOM section when all of it have been loaded and
// executed
var doResolve = null;
var _allScriptsLoaded = new Promise(function (resolve) {
    if (doResolve) {
        resolve();
    } else {
        doResolve = resolve;
    }
}).then(function () {
    stopWaitingLazy();
});
if (document.readyState === 'complete') {
    setTimeout(_loadScripts, 0);
} else {
    window.addEventListener('load', function () {
        setTimeout(_loadScripts, 0);
    });
}

/**
 * @param {DOMElement[]} scripts
 * @param {integer} index
 */
function _loadScripts(scripts, index) {
    if (scripts === undefined) {
        scripts = document.querySelectorAll('script[data-src]');
    }
    if (index === undefined) {
        index = 0;
    }
    if (index >= scripts.length) {
        if (typeof doResolve === 'function') {
            doResolve();
        } else {
            doResolve = true;
        }
        return;
    }
    var script = scripts[index];
    script.addEventListener('load', _loadScripts.bind(this, scripts, index + 1));
    script.src = script.dataset.src;
    script.removeAttribute('data-src');
}

return {
    loadScripts: _loadScripts,
    allScriptsLoaded: _allScriptsLoaded,
};
});