summaryrefslogtreecommitdiffstats
path: root/public/js/define.js
blob: a3ce8c67a1be44cdc15bf524101ec5c75c45a673 (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
112
113
114
115
116
117
118
/*! Icinga Web 2 | (c) 2020 Icinga GmbH | GPLv2+ */

(function(window) {

    'use strict';

    /**
     * Provide a reference to be later required by foreign code
     *
     * @param {string} name Optional, defaults to the name (and path) of the file
     * @param {string[]} requirements Optional, list of required references, may be relative if from the same package
     * @param {function} factory Required, function that accepts as many params as there are requirements and that
     *                           produces a value to be referenced
     */
    var define = function (name, requirements, factory) {
        define.defines[name] = {
            requirements: requirements,
            factory: factory,
            ref: null
        }

        define.resolve(name);
    }

    /**
     * Return whether the given name references a value
     *
     * @param {string} name The absolute name of the reference
     * @return {boolean}
     */
    define.has = function (name) {
        return name in define.defines && define.defines[name]['ref'] !== null;
    }

    /**
     * Get the value of a reference
     *
     * @param {string} name The absolute name of the reference
     * @return {*}
     */
    define.get = function (name) {
        return define.defines[name]['ref'];
    }

    /**
     * Set the value of a reference
     *
     * @param {string} name The absolute name of the reference
     * @param {*} ref The value to reference
     */
    define.set = function (name, ref) {
        define.defines[name]['ref'] = ref;
    }

    /**
     * Resolve a reference and, if successful, dependent references
     *
     * @param {string} name The absolute name of the reference
     * @return {boolean}
     */
    define.resolve = function (name) {
        var requirements = define.defines[name]['requirements'];

        var exports, ref;
        var requiredRefs = [];
        for (var i = 0; i < requirements.length; i++) {
            if (define.has(requirements[i])) {
                ref = define.get(requirements[i]);
            } else if (requirements[i] === 'exports') {
                exports = ref = {};
            } else {
                return false;
            }

            requiredRefs.push(ref);
        }

        var factory = define.defines[name]['factory'];
        var resolved = factory.apply(null, requiredRefs);

        if (typeof exports === 'object') {
            if (typeof resolved !== 'undefined') {
                throw new Error('Factory for ' + name + ' returned, although exports were populated');
            }

            resolved = exports;
        }

        define.set(name, resolved);

        for (var definedName in define.defines) {
            if (define.defines[definedName]['requirements'].indexOf(name) >= 0) {
                define.resolve(definedName);
            }
        }
    }

    /**
     * Require a reference
     *
     * @param {string} name The absolute name of the reference
     * @return {*}
     */
    var require = function(name) {
        if (define.has(name)) {
            return define.get(name);
        }

        throw new ReferenceError(name + ' is not defined');
    }

    define.icinga = true;
    define.defines = {};

    window.define = define;
    window.require = require;

})(window);