1/*
2 * Copyright (c) 2021. ComboStrap, Inc. and its affiliates. All Rights Reserved.
3 *
4 * This source code is licensed under the GPL license found in the
5 * COPYING  file in the root directory of this source tree.
6 *
7 * @license  GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html)
8 * @author   ComboStrap <support@combostrap.com>
9 *
10 */
11let WEBCODE = (function () {
12    let exp = {};
13
14    /**
15     * A log entry is used because the HTML page
16     * may be not yet fully loaded
17     * when the console.log or console.table is called
18     * in a html script tag inside HTML
19     */
20    let logs = [];
21
22    function WebConsole() {
23
24        let webConsoleElement = document.querySelector("#webCodeConsole");
25
26        let appendLine = function (text) {
27            let webConsoleLine = document.createElement("p");
28            webConsoleLine.className = "webCodeConsoleLine";
29            webConsoleLine.innerHTML = text;
30            appendChild(webConsoleLine);
31        };
32        let appendChild = function (element) {
33            webConsoleElement.appendChild(element);
34        };
35
36        let printTable = function (input) {
37            if (Array.isArray(input) !== true) {
38
39                appendLine("The variable of the function console.table must be an array.");
40
41            } else {
42                if (input.length <= 0) {
43
44                    appendLine("The variable of the console.table has no elements.");
45
46                } else {
47                    // HTML Headers
48                    let tableElement = document.createElement("table");
49                    let theadElement = document.createElement("thead");
50                    let tbodyElement = document.createElement("tbody");
51                    let trHeadElement = document.createElement("tr");
52
53                    tableElement.appendChild(theadElement);
54                    tableElement.appendChild(tbodyElement);
55                    theadElement.appendChild(trHeadElement);
56
57
58                    for (let i = 0; i < input.length; i++) {
59
60                        let element = input[i];
61
62                        // First iteration, we pick the headers
63                        if (i === 0) {
64
65                            if (typeof element === 'object') {
66                                for (let prop in element) {
67                                    let thElement = document.createElement("th");
68                                    thElement.innerHTML = print(prop);
69                                    trHeadElement.appendChild(thElement);
70                                }
71                            } else {
72                                // Header
73                                let thElement = document.createElement("th");
74                                thElement.innerHTML = "Values";
75                                trHeadElement.appendChild(thElement);
76                            }
77
78                        }
79
80                        let trBodyElement = document.createElement("tr");
81                        tbodyElement.appendChild(trBodyElement);
82
83                        if (typeof input[0] === 'object') {
84                            for (let prop in element) {
85                                let tdElement = document.createElement("td");
86                                tdElement.innerHTML = print(element[prop]);
87                                trBodyElement.appendChild(tdElement);
88                            }
89                        } else {
90                            let tdElement = document.createElement("td");
91                            tdElement.innerHTML = print(element);
92                            let trElement = document.createElement("tr");
93                            trElement.appendChild(tdElement);
94                        }
95
96                    }
97                    appendChild(tableElement);
98
99                }
100            }
101        }
102
103        let printLog = function (input) {
104            let s;
105            if (typeof input === "object") {
106                s = "{\n";
107                let keys = Object.keys(input);
108                for (let i = 0; i < keys.length; i++) {
109                    s += "  " + keys[i] + " : " + input[keys[i]] + ";\n";
110                }
111                s += "}\n";
112            } else {
113                s = String(input);
114            }
115            s = htmlEntities(s);
116            // the BR replacement must be after the htmlEntities function ...
117            s = s.replace(/\n/g, '<BR>')
118            appendLine(s);
119        }
120
121        let htmlEntities = function (str) {
122            // from https://css-tricks.com/snippets/javascript/htmlentities-for-javascript/
123            return String(str)
124                .replace(/&/g, '&amp;')
125                .replace(/</g, '&lt;')
126                .replace(/>/g, '&gt;')
127                .replace(/"/g, '&quot;')
128                .replace(/ /g, '&nbsp;');
129        }
130
131        let print = function (v) {
132            if (typeof v === 'undefined') {
133                return "(Undefined)"; // Undefined == null, therefore it must be in first position
134            } else if (Array.isArray(v)) {
135                if (v.length === 0) {
136                    return "(Empty Array)";
137                } else {
138                    return v;
139                }
140            } else if (typeof v === 'string') {
141                if (v.length === 0) {
142                    return "(Empty String)"
143                } else {
144                    return v;
145                }
146            } else if (v === null) {
147                return "(null)";
148            } else {
149                return v;
150            }
151        };
152
153        // Public
154        return {
155            printTable: printTable,
156            printLog: printLog
157        };
158
159    }
160
161
162    exp.addLogEntry = function (input) {
163        logs.push({
164            type: "log",
165            data: input
166        })
167    }
168    exp.addTableEntry = function (input) {
169        logs.push({
170            type: "table",
171            data: input
172        })
173    }
174    exp.flushLogs = function () {
175        let webConsole = new WebConsole();
176        for (const log of logs) {
177            let {type, data} = log;
178            if (type === "log") {
179                webConsole.printLog(data);
180            } else {
181                webConsole.printTable(data);
182            }
183        }
184        logs = [];
185    }
186    return exp;
187})();
188
189
190window.console.log = function (input) {
191    WEBCODE.addLogEntry(input);
192};
193
194// https://developer.mozilla.org/en-US/docs/Web/API/Console/table
195window.console.table = function (input) {
196    WEBCODE.addTableEntry(input);
197};
198
199window.addEventListener("DOMContentLoaded", function () {
200    WEBCODE.flushLogs();
201    // log may be added later, flush the logs at interval
202    window.setInterval(WEBCODE.flushLogs,2000)
203})
204
205