Scoprire che cosa il numero di riga di un elemento nel Regno si verifica su in Javascript?
-
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.
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, '<').replace(/>/g, '>'), '</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:)