Scoprire che cosa il numero di riga di un elemento nel Regno si verifica su in Javascript?

StackOverflow https://stackoverflow.com/questions/2044642

  •  20-09-2019
  •  | 
  •  

Domanda

Anche se non ho mai sentito parlare di questo, ma, è possibile recuperare un nodo dal DOM utilizzando JS, e poi scoprire su quale riga del file che si è verificato il nodo?

Sono aperto a qualsiasi cosa, browser alternativi plugins / add-on, ecc ... non ha bisogno di essere cross-browser per dire.

presumo che questo sarebbe possibile in qualche modo se si considera che alcuni debugger JS sono in grado di trovare il numero di riga all'interno di un tag script, ma non sono del tutto sicuro.

È stato utile?

Soluzione

Ok, mi perdoni per quanto grande sia questo. Ho pensato che questo era una domanda molto interessante, ma durante il gioco con esso, ho capito subito che innerHTML ed il suo ilk sono abbastanza inaffidabili WRT mantenendo gli spazi bianchi, commenti, ecc Con questo in mente, sono caduto di nuovo a realtà tirando giù una copia completa del sorgente in modo che io possa essere assolutamente sicuro ho ottenuto il sorgente completo. Ho quindi utilizzato jQuery e pochi (relativamente piccolo) regex di trovare la posizione di ogni nodo. Sembra funzionare bene anche se sono sicuro che ho perso alcuni casi limite. E, si, si, regex e due problemi, bla bla bla.

Modifica come un esercizio di costruzione plugin jQuery, ho modificato il mio codice di funzionare ragionevolmente bene come un autonomo plug con una esempio simile al html trovare qui sotto (che lascerò qui per i posteri). Ho cercato di rendere il codice un po 'più robusto (come ad esempio la società di movimentazione tag all'interno di stringhe tra virgolette, come onclick), ma il più grande problema che rimane è che non si può tenere conto di eventuali modifiche alla pagina, ad esempio elementi aggiunta. Avrei bisogno probabilmente bisogno di usare un iframe al posto di una chiamata AJAX per gestire questo caso.

<html>
    <head id="node0">
    <!-- first comment -->
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
        <style id="node1">
/*          div { border: 1px solid black; } */
            pre { border: 1px solid black; }
        </style>
    <!-- second comment -->
        <script>
            $(function() {

                // fetch and display source
                var source;
                $.ajax({
                    url: location.href,
                    type: 'get',
                    dataType: 'text',
                    success: function(data) {
                        source = data;


                        var lines = data.split(/\r?\n/);
                        var html = $.map(lines, function(line, i) {
                            return ['<span id="line_number_', i, '"><strong>', i, ':</strong> ', line.replace(/</g, '&lt;').replace(/>/g, '&gt;'), '</span>'].join('');
                        }).join('\n');

                        // now sanitize the raw html so you don't get false hits in code or comments
                        var inside = false;
                        var tag = '';
                        var closing = {
                            xmp: '<\\/\\s*xmp\\s*>',
                            script: '<\\/\\s*script\\s*>',
                            '!--': '-->'
                        };
                        var clean_source = $.map(lines, function(line) {
                            if (inside && line.match(closing[tag])) {
                                var re = new RegExp('.*(' + closing[tag] + ')', 'i');
                                line = line.replace(re, "$1");
                                inside = false;
                            } else if (inside) {
                                line = '';
                            }

                            if (line.match(/<(script|!--)/)) {
                                tag = RegExp.$1;
                                line = line.replace(/<(script|xmp|!--)[^>]*.*(<(\/(script|xmp)|--)?>)/i, "<$1>$2");
                                var re = new RegExp(closing[tag], 'i');
                                inside = ! (re).test(line);
                            }
                            return line;
                        });

                        // nodes we're looking for
                        var nodes = $.map([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(num) { return $('#node' + num) });

                        // now find each desired node in both the DOM and the source
                        var line_numbers = $.map(nodes, function(node) {
                            var tag = node.attr('tagName');
                            var tags = $(tag);
                            var index = tags.index(node) + 1;

                            var count = 0;
                            for (var i = 0; i < clean_source.length; i++) {
                                var re = new RegExp('<' + tag, 'gi');
                                var matches = clean_source[i].match(re);
                                if (matches && matches.length) {
                                    count += matches.length;
                                    if (count >= index) {
                                        console.debug(node, tag, index, count, i);
                                        return i;
                                    }
                                }
                            }


                            return count;
                        });

                        // saved till end to avoid affecting source html
                        $('#source_pretty').html(html);
                        $('#source_raw').text(source);
                        $('#source_clean').text(clean_source.join('\n'));

                        $.each(line_numbers, function() { $('#line_number_' + this).css('background-color', 'orange'); });
                    },
                });

                var false_matches = [
                    "<div>",
                    "<div>",
                    "</div>",
                    "</div>"
                ].join('');

            });
        </script>
    </head>
    <!-- third comment -->
    <body id="node2">
        <div>
            <pre id="source_pretty">
            </pre>
            <pre id="source_raw">
            </pre>
            <pre id="source_clean">
            </pre>
        </div>

        <div id="node3">
            <xmp>
                <code>
                // <xmp> is deprecated, you should put it in <code> instead
                </code>
            </xmp>
        </div>

    <!-- fourth comment -->
<div><div><div><div><div><div><span><div id="node4"><span><span><b><em>
<i><strong><pre></pre></strong></i><div><div id="node5"><div></div></div></div></em>
</b></span><span><span id="node6"></span></span></span></div></span></div></div></div></div></div></div>


        <div>
            <div>
                <div id="node7">
                    <div>
                        <div>
                            <div id="node8">
                                <span>
    <!-- fifth comment -->
                                    <div>
                                        <span>
                                            <span>
                                                <b>
                                                    <em id="node9">
                                                        <i>
                                                            <strong>
                                                                <pre>
                                                                </pre>
                                                            </strong>
                                                        </i>
                                                        <div>
                                                            <div>
                                                                <div>
                                                                </div>
                                                            </div>
                                                        </div>
                                                    </em>
                                                </b>
                                            </span>
                                            <span>
                                                <span id="node10">
                                                </span>
                                            </span>
                                        </span>
                                    </div>
                                </span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

Altri suggerimenti

Una cosa come questa?

var wholeDocument = document.getElementsByTagName('html')[0]
var findNode = document.getElementById('whatever')
var documentUpToFindNode = wholeDocument.substr(0, wholeDocument.indexOf(findNode.outerHTML))
var nlsUpToFindNode = documentUpToFindNode.match(/\n/g).length

Questo può essere fatto. Inizia a ricevere il nodo più alto nel documento come questo:

var htmlNode = document.getElementsByTagName('html')[0];
var node = htmlNode;
while (node.previousSibling !== null) {
    node = node.previousSibling;
}
var firstNode = node;

(questo codice è stato testato e recuperato sia il nodo doctype nonché commenti sopra nodo html)

ciclo Poi l'utente attraverso tutti i nodi (entrambi fratelli e figli). In IE, potrai vedere solo gli elementi e commenti (non nodi di testo), quindi sarà meglio usare FF o cromato o qualcosa (hai detto che non avrebbe dovuto essere cross browser).

Quando si arriva a ciascun testo del nodo , analizzarlo per cercare ritorni a capo.

Si potrebbe provare: -

 - start at the 'whatever' node, 
 - traverse to each previous node back to the doc begining while concatenating the html of each node, 
 - then count the new lines in your collected HTML.

Inserisci il codice una volta che il dado fuori coz questo è una buona domanda:)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top