• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aplus-framework / mvc / 16927505441

22 Jul 2025 07:08PM UTC coverage: 100.0%. Remained the same
16927505441

push

github

natanfelles
Add info about order in which commands are added to the console

1836 of 1836 relevant lines covered (100.0%)

10.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/Debug/Views/toggle-views-hints.php
1
<?php
2
/**
3
 * This file contains snippets originally created in CodeIgniter 4 and is
4
 * MIT licensed.
5
 *
6
 * A big thank you to all the contributors, without them this wouldn't be
7
 * possible.
8
 *
9
 * @see https://github.com/codeigniter4/CodeIgniter4/issues/758
10
 */
11
?><button id="debugbar-toggle-views">Toggle Views Hints</button>
2✔
12
<style>
2✔
13
    .debugbar-view.show-view {
2✔
14
        border: 1px solid;
2✔
15
        margin: 2px;
2✔
16
    }
2✔
17

18
    .debugbar-view-path {
2✔
19
        background: #000;
2✔
20
        border-bottom: 1px solid #222;
2✔
21
        color: #fff;
2✔
22
        font-family: monospace;
2✔
23
        font-size: 12px;
2✔
24
        letter-spacing: normal;
2✔
25
        min-height: 16px;
2✔
26
        padding: 2px;
2✔
27
        text-align: left;
2✔
28
    }
2✔
29

30
    .show-view .debugbar-view-path {
2✔
31
        display: block !important;
2✔
32
    }
2✔
33

34
    .debugbar-view.show-view {
2✔
35
        border-color: #222;
2✔
36
    }
2✔
37
</style>
2✔
38
<script>
2✔
39
    function toggleViewsHints() {
2✔
40
        let nodeList = []; // [ Element, NewElement( 1 )/OldElement( 0 ) ]
2✔
41
        let sortedComments = [];
2✔
42
        let comments = [];
2✔
43
        let getComments = function () {
2✔
44
            let nodes = [];
2✔
45
            let result = [];
2✔
46
            let xpathResults = document.evaluate(
2✔
47
                "//comment()[starts-with(., ' DEBUG-VIEW')]",
2✔
48
                document,
2✔
49
                null,
2✔
50
                XPathResult.ANY_TYPE,
2✔
51
                null,
2✔
52
            );
2✔
53
            let nextNode = xpathResults.iterateNext();
2✔
54
            while (nextNode) {
2✔
55
                nodes.push(nextNode);
2✔
56
                nextNode = xpathResults.iterateNext();
2✔
57
            }
2✔
58
            // sort comment by opening and closing tags
2✔
59
            for (let i = 0; i < nodes.length; ++i) {
2✔
60
                // get file path + name to use as key
2✔
61
                let path = nodes[i].nodeValue.substring(
2✔
62
                    18,
2✔
63
                    nodes[i].nodeValue.length - 1,
2✔
64
                );
2✔
65
                if (nodes[i].nodeValue[12] === 'S') {
2✔
66
                    // simple check for start comment
2✔
67
                    // create new entry
2✔
68
                    result[path] = [nodes[i], null];
2✔
69
                } else if (result[path]) {
2✔
70
                    // add to existing entry
2✔
71
                    result[path][1] = nodes[i];
2✔
72
                }
2✔
73
            }
2✔
74
            return result;
2✔
75
        };
2✔
76
        // find node that has TargetNode as parentNode
2✔
77
        let getParentNode = function (node, targetNode) {
2✔
78
            if (node.parentNode === null) {
2✔
79
                return null;
2✔
80
            }
2✔
81
            if (node.parentNode !== targetNode) {
2✔
82
                return getParentNode(node.parentNode, targetNode);
2✔
83
            }
2✔
84
            return node;
2✔
85
        };
2✔
86
        // define invalid & outer ( also invalid ) elements
2✔
87
        const INVALID_ELEMENTS = ['NOSCRIPT', 'SCRIPT', 'STYLE'];
2✔
88
        const OUTER_ELEMENTS = ['HTML', 'BODY', 'HEAD'];
2✔
89
        let getValidElementInner = function (node, reverse) {
2✔
90
            // handle invalid tags
2✔
91
            if (OUTER_ELEMENTS.indexOf(node.nodeName) !== -1) {
2✔
92
                for (let i = 0; i < document.body.children.length; ++i) {
2✔
93
                    let index = reverse
2✔
94
                        ? document.body.children.length - (i + 1)
2✔
95
                        : i;
2✔
96
                    let element = document.body.children[index];
2✔
97
                    // skip invalid tags
2✔
98
                    if (INVALID_ELEMENTS.indexOf(element.nodeName) !== -1) {
2✔
99
                        continue;
2✔
100
                    }
2✔
101
                    return [element, reverse];
2✔
102
                }
2✔
103
                return null;
2✔
104
            }
2✔
105
            // get to next valid element
2✔
106
            while (
2✔
107
                node !== null &&
2✔
108
                INVALID_ELEMENTS.indexOf(node.nodeName) !== -1
2✔
109
                ) {
2✔
110
                node = reverse
2✔
111
                    ? node.previousElementSibling
2✔
112
                    : node.nextElementSibling;
2✔
113
            }
2✔
114
            // return non array if we couldnt find something
2✔
115
            if (node === null) {
2✔
116
                return null;
2✔
117
            }
2✔
118
            return [node, reverse];
2✔
119
        };
2✔
120
        // get next valid element ( to be safe to add divs )
2✔
121
        // @return [ element, skip element ] or null if we couldnt find a valid place
2✔
122
        let getValidElement = function (nodeElement) {
2✔
123
            if (nodeElement) {
2✔
124
                if (nodeElement.nextElementSibling !== null) {
2✔
125
                    return (
2✔
126
                        getValidElementInner(
2✔
127
                            nodeElement.nextElementSibling,
2✔
128
                            false,
2✔
129
                        ) ||
2✔
130
                        getValidElementInner(
2✔
131
                            nodeElement.previousElementSibling,
2✔
132
                            true,
2✔
133
                        )
2✔
134
                    );
2✔
135
                }
2✔
136
                if (nodeElement.previousElementSibling !== null) {
2✔
137
                    return getValidElementInner(
2✔
138
                        nodeElement.previousElementSibling,
2✔
139
                        true,
2✔
140
                    );
2✔
141
                }
2✔
142
            }
2✔
143
            // something went wrong! -> element is not in DOM
2✔
144
            return null;
2✔
145
        };
2✔
146

147
        function showHints() {
2✔
148
            // Had AJAX? Reset view blocks
2✔
149
            sortedComments = getComments();
2✔
150
            for (let key in sortedComments) {
2✔
151
                let startElement = getValidElement(sortedComments[key][0]);
2✔
152
                let endElement = getValidElement(sortedComments[key][1]);
2✔
153
                // skip if we couldnt get a valid element
2✔
154
                if (startElement === null || endElement === null) {
2✔
155
                    continue;
2✔
156
                }
2✔
157
                // find element which has same parent as startelement
2✔
158
                let jointParent = getParentNode(
2✔
159
                    endElement[0],
2✔
160
                    startElement[0].parentNode,
2✔
161
                );
2✔
162
                if (jointParent === null) {
2✔
163
                    // find element which has same parent as endelement
2✔
164
                    jointParent = getParentNode(
2✔
165
                        startElement[0],
2✔
166
                        endElement[0].parentNode,
2✔
167
                    );
2✔
168
                    if (jointParent === null) {
2✔
169
                        // both tries failed
2✔
170
                        continue;
2✔
171
                    } else {
2✔
172
                        startElement[0] = jointParent;
2✔
173
                    }
2✔
174
                } else {
2✔
175
                    endElement[0] = jointParent;
2✔
176
                }
2✔
177
                let debugDiv = document.createElement('div'); // holder
2✔
178
                let debugPath = document.createElement('div'); // path
2✔
179
                let childArray = startElement[0].parentNode.childNodes; // target child array
2✔
180
                let parent = startElement[0].parentNode;
2✔
181
                let start, end;
2✔
182
                // setup container
2✔
183
                debugDiv.classList.add('debugbar-view');
2✔
184
                debugDiv.classList.add('show-view');
2✔
185
                debugPath.classList.add('debugbar-view-path');
2✔
186
                debugPath.innerText = key;
2✔
187
                debugDiv.appendChild(debugPath);
2✔
188
                // calc distance between them
2✔
189
                // start
2✔
190
                for (let i = 0; i < childArray.length; ++i) {
2✔
191
                    // check for comment ( start & end ) -> if its before valid start element
2✔
192
                    if (
2✔
193
                        childArray[i] === sortedComments[key][1] ||
2✔
194
                        childArray[i] === sortedComments[key][0] ||
2✔
195
                        childArray[i] === startElement[0]
2✔
196
                    ) {
2✔
197
                        start = i;
2✔
198
                        if (childArray[i] === sortedComments[key][0]) {
2✔
199
                            start++; // increase to skip the start comment
2✔
200
                        }
2✔
201
                        break;
2✔
202
                    }
2✔
203
                }
2✔
204
                // adjust if we want to skip the start element
2✔
205
                if (startElement[1]) {
2✔
206
                    start++;
2✔
207
                }
2✔
208
                // end
2✔
209
                for (let i = start; i < childArray.length; ++i) {
2✔
210
                    if (childArray[i] === endElement[0]) {
2✔
211
                        end = i;
2✔
212
                        // dont break to check for end comment after end valid element
2✔
213
                    } else if (childArray[i] === sortedComments[key][1]) {
2✔
214
                        // if we found the end comment, we can break
2✔
215
                        end = i;
2✔
216
                        break;
2✔
217
                    }
2✔
218
                }
2✔
219
                // move elements
2✔
220
                let number = end - start;
2✔
221
                if (endElement[1]) {
2✔
222
                    number++;
2✔
223
                }
2✔
224
                for (let i = 0; i < number; ++i) {
2✔
225
                    if (INVALID_ELEMENTS.indexOf(childArray[start]) !== -1) {
2✔
226
                        // skip invalid childs that can cause problems if moved
2✔
227
                        start++;
2✔
228
                        continue;
2✔
229
                    }
2✔
230
                    debugDiv.appendChild(childArray[start]);
2✔
231
                }
2✔
232
                // add container to DOM
2✔
233
                nodeList.push(parent.insertBefore(debugDiv, childArray[start]));
2✔
234
            }
2✔
235
            localStorage.setItem('debugbar-view', 'show');
2✔
236
            btn.classList.add('active');
2✔
237
        }
2✔
238

239
        function hideHints() {
2✔
240
            for (let i = 0; i < nodeList.length; ++i) {
2✔
241
                let index;
2✔
242
                // find index
2✔
243
                for (
2✔
244
                    let j = 0;
2✔
245
                    j < nodeList[i].parentNode.childNodes.length;
2✔
246
                    ++j
2✔
247
                ) {
2✔
248
                    if (nodeList[i].parentNode.childNodes[j] === nodeList[i]) {
2✔
249
                        index = j;
2✔
250
                        break;
2✔
251
                    }
2✔
252
                }
2✔
253
                // move child back
2✔
254
                while (nodeList[i].childNodes.length !== 1) {
2✔
255
                    nodeList[i].parentNode.insertBefore(
2✔
256
                        nodeList[i].childNodes[1],
2✔
257
                        nodeList[i].parentNode.childNodes[index].nextSibling,
2✔
258
                    );
2✔
259
                    index++;
2✔
260
                }
2✔
261
                nodeList[i].parentNode.removeChild(nodeList[i]);
2✔
262
            }
2✔
263
            nodeList.length = 0;
2✔
264
            localStorage.removeItem('debugbar-view')
2✔
265
            btn.classList.remove('active');
2✔
266
        }
2✔
267

268
        let btn = document.querySelector('#debugbar-toggle-views');
2✔
269
        // If the Views Collector is inactive stops here
2✔
270
        if (!btn) {
2✔
271
            return;
2✔
272
        }
2✔
273
        btn.onclick = function () {
2✔
274
            if (localStorage.getItem('debugbar-view')) {
2✔
275
                hideHints();
2✔
276
                return;
2✔
277
            }
2✔
278
            showHints();
2✔
279
        };
2✔
280
        // Determine Hints state on page load
2✔
281
        if (localStorage.getItem('debugbar-view')) {
2✔
282
            showHints();
2✔
283
        }
2✔
284
    }
2✔
285

286
    toggleViewsHints();
2✔
287
</script>
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc