javascript - ejemplos - Extraiga el DOM actual e imprímalo como una cadena, con los estilos intactos
title css (8)
¿No puedes hacer document.getElementsByTagName (''body'') [0] .innerHTML? Cuando hago cambios en el inspector y luego ingreso el javascript anterior en la consola, devuelve el HTML actualizado.
EDIT: Acabo de intentar poner ese script en una función y adjuntarlo a un evento onclick. Hice algunas actualizaciones en el inspector, haga clic en el botón y funcionó:
HTML
<button onclick="printDOM()">Print DOM</button>
Javascript
function printDOM() {
console.log(document.getElementsByTagName(''body'')[0].innerHTML) ;
}
Me gustaría poder tomar mi DOM, como es, y convertirlo en una cadena. Digamos que abro el inspector y hago un cambio en la propiedad margen izquierdo de un elemento en particular. Ese cambio se debe reflejar en mi cadena.
La función debe tomar correctamente todos los estilos aplicados actualmente a un elemento (excluyendo los valores predeterminados) e incluirlos en el estilo en línea para ese elemento.
He escrito una "solución" que ha demostrado ser inadecuada. La función getMatchedCSSRules
en webkit es extremadamente delicada, y no he podido determinar por qué a veces funciona y no funciona otras veces. Por lo tanto, me gustaría evitar usar esta función a menos que funcione el 100% del tiempo. Del mismo modo, la función getComputedStyle
tiene problemas propios. Si usa el inspector para cambiar el elemento #footer en esta página para que sea 7px solid red
lugar de 7px solid black
, el cambio se reflejará cuando ejecute getComputedStyle(document.getElementById(''footer'')).cssText
en la consola pero también me dará una serie de propiedades heredadas que nunca fueron modificadas por el usuario que usa el inspector o por las hojas de estilo en la página.
Estoy buscando una solución que funcione con webkit: la compatibilidad entre navegadores no es un problema en este momento.
¡Gracias!
Basándome en la respuesta de Luc125, he creado una extensión de herramientas para desarrolladores para Chrome que incorpora ese código para capturar estilos y marcas para un fragmento de página. La extensión está en Chrome Web Store y está en Github . La opción de salida "Estilos calculados" usa ese método.
Bien, tal vez me esté perdiendo algo aquí, pero ¿no es la cadena que desea solo document.documentElement.innerHTML
? Una prueba rápida con Chrome verifica que recoge los cambios realizados en las Herramientas del desarrollador para diseñar los atributos que describe. Los nombres de clase asignados no se expanden (por ejemplo, no tendrá idea de lo que está haciendo class="superfuntime"
), pero si estoy leyendo su pregunta correctamente, no ha indicado la necesidad de eso.
Característica de Chrome - Imprimiendo el DOM:
La bandera --dump-dom
imprime document.body.innerHTML
en la --dump-dom
:
chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/
Leer more
Creo que esto podría ser una solución (¡me tomó casi un día entero!).
Devuelve una cadena que representa el DOM de cualquier elemento, con todos los estilos externos incluidos en los atributos de "estilo" excepto los valores predeterminados, y no modifica ese elemento de forma permanente.
Por ejemplo: console.log(document.body.serializeWithStyles());
Puede cargar este código en la línea de comandos del inspector web o desde una etiqueta de script en el elemento del cuerpo pero NO en el elemento principal porque requiere la existencia de document.body.
Lo he probado en el escritorio Safari 5 (no tengo la versión móvil).
Funciona así:
Para cada elemento en el DOM:
1) almacenamiento en caché del valor de la propiedad style.cssText, que representa el estilo en línea, en una matriz;
2) llamando a getComputedStyle en el elemento;
3) comprobando si tenemos la tabla de búsqueda de valores por defecto de css correspondiente al nombre de etiqueta de este elemento;
4) construyéndolo si no;
5) iterando a través del resultado, encontrando qué valores no son predeterminados usando la tabla de búsqueda;
6) aplicar esos valores de estilo no predeterminados al elemento.
Entonces almacenando el externalHTML como el resultado;
Para cada elemento, restaurar los estilos en línea desde el caché;
Devolviendo el resultado previamente almacenado.
El código:
Element.prototype.serializeWithStyles = (function () {
// Mapping between tag names and css default values lookup tables. This allows to exclude default values in the result.
var defaultStylesByTagName = {};
// Styles inherited from style sheets will not be rendered for elements with these tag names
var noStyleTags = {"BASE":true,"HEAD":true,"HTML":true,"META":true,"NOFRAME":true,"NOSCRIPT":true,"PARAM":true,"SCRIPT":true,"STYLE":true,"TITLE":true};
// This list determines which css default values lookup tables are precomputed at load time
// Lookup tables for other tag names will be automatically built at runtime if needed
var tagNames = ["A","ABBR","ADDRESS","AREA","ARTICLE","ASIDE","AUDIO","B","BASE","BDI","BDO","BLOCKQUOTE","BODY","BR","BUTTON","CANVAS","CAPTION","CENTER","CITE","CODE","COL","COLGROUP","COMMAND","DATALIST","DD","DEL","DETAILS","DFN","DIV","DL","DT","EM","EMBED","FIELDSET","FIGCAPTION","FIGURE","FONT","FOOTER","FORM","H1","H2","H3","H4","H5","H6","HEAD","HEADER","HGROUP","HR","HTML","I","IFRAME","IMG","INPUT","INS","KBD","KEYGEN","LABEL","LEGEND","LI","LINK","MAP","MARK","MATH","MENU","META","METER","NAV","NOBR","NOSCRIPT","OBJECT","OL","OPTION","OPTGROUP","OUTPUT","P","PARAM","PRE","PROGRESS","Q","RP","RT","RUBY","S","SAMP","SCRIPT","SECTION","SELECT","SMALL","SOURCE","SPAN","STRONG","STYLE","SUB","SUMMARY","SUP","SVG","TABLE","TBODY","TD","TEXTAREA","TFOOT","TH","THEAD","TIME","TITLE","TR","TRACK","U","UL","VAR","VIDEO","WBR"];
// Precompute the lookup tables.
for (var i = 0; i < tagNames.length; i++) {
if(!noStyleTags[tagNames[i]]) {
defaultStylesByTagName[tagNames[i]] = computeDefaultStyleByTagName(tagNames[i]);
}
}
function computeDefaultStyleByTagName(tagName) {
var defaultStyle = {};
var element = document.body.appendChild(document.createElement(tagName));
var computedStyle = getComputedStyle(element);
for (var i = 0; i < computedStyle.length; i++) {
defaultStyle[computedStyle[i]] = computedStyle[computedStyle[i]];
}
document.body.removeChild(element);
return defaultStyle;
}
function getDefaultStyleByTagName(tagName) {
tagName = tagName.toUpperCase();
if (!defaultStylesByTagName[tagName]) {
defaultStylesByTagName[tagName] = computeDefaultStyleByTagName(tagName);
}
return defaultStylesByTagName[tagName];
}
return function serializeWithStyles() {
if (this.nodeType !== Node.ELEMENT_NODE) { throw new TypeError(); }
var cssTexts = [];
var elements = this.querySelectorAll("*");
for ( var i = 0; i < elements.length; i++ ) {
var e = elements[i];
if (!noStyleTags[e.tagName]) {
var computedStyle = getComputedStyle(e);
var defaultStyle = getDefaultStyleByTagName(e.tagName);
cssTexts[i] = e.style.cssText;
for (var ii = 0; ii < computedStyle.length; ii++) {
var cssPropName = computedStyle[ii];
if (computedStyle[cssPropName] !== defaultStyle[cssPropName]) {
e.style[cssPropName] = computedStyle[cssPropName];
}
}
}
}
var result = this.outerHTML;
for ( var i = 0; i < elements.length; i++ ) {
elements[i].style.cssText = cssTexts[i];
}
return result;
}
})();
En caso de que desee capturar toda la página, es más fácil obtener todas las hojas de estilo no en línea y alinearlas.
El enfoque en la respuesta aceptada es magnífico, pero bastante lento y toca todo el documento.
Tomé el siguiente enfoque para capturar una página que incluye estilo:
document.documentElement.outerHTML;
obtener todas las hojas de estilo de la API
document.styleSheets
En la línea de:
function captureCss(){
var cssrules = "";
var sheets = document.styleSheets;
for(var i = 0; i<sheets.length; i++){
if(!sheets[i].disabled && sheets[i].href != null) { // or sheets[i].href.nodeName == ''LINK''
if(sheets[i].rules == null){ // can be null because of cross origin policy
try{
var fetched = XHR GET(sheets[i].href); // works nicely because it hits the cache
if(fetched){
cssrules += "<style>/n"+fetched+"/n</style>/n"
}
}catch(e){
console.log(e);
}
continue;
}
for(var j=0;j<sheets[i].rules.length;j++){
cssrules += "<style>/n"+sheets[i].rules[j].cssText+"/n</style>/n"
}
}
}
return cssrules;
}
- Agregue los
cssrules
capturados como la primera cosa del encabezado en el texto htmlouterHtml
De esta manera obtienes una página de estilo autónoma.
Esto es obviamente menos aplicable para el contenido parcial.
Tal vez la biblioteca de cierre de Google tiene una solución para usted.
Hay un código que parece hacer lo que necesita, es decir, calcular las reglas CSS para reproducir la misma apariencia de un elemento fuera de su posición actual en el dom (en su caso, necesitan transferir estilos a un iframe para usarlo como un editor en línea sin problemas).
Citando desde el archivo fuente style.js :
Provides utility routines for copying modified
CSSRule objects from the parent document into iframes so that any
content in the iframe will be styled as if it was inline in the parent
document.
<p>
For example, you might have this CSS rule:
#content .highlighted { background-color: yellow; }
And this DOM structure:
<div id="content">
<iframe />
</div>
Then inside the iframe you have:
<body>
<div class="highlighted">
</body>
If you copied the CSS rule directly into the iframe, it wouldn''t match the
.highlighted div. So we rewrite the original stylesheets based on the
context where the iframe is going to be inserted. In this case the CSS
selector would be rewritten to:
body .highlighted { background-color: yellow; }
</p>
Internet Explorer -> Herramientas del desarrollador -> DOM Explorer
Seleccione el elemento y haga clic derecho -> "Copiar elemento con estilos".