Me gustaría ser capaz de tomar mis DOM, como es, y convertirlo en una cadena. Digamos que me abra el inspector y hacer un cambio en la margen izquierda de la propiedad de un elemento en particular. Que el cambio debe reflejarse en mi cadena.

La función debe tomar todos los estilos que actualmente se aplica a un elemento (excepto valores por defecto) y los incluyen en la línea de estilo para el elemento.

He escrito una ‘solución’ que ha demostrado ser insuficiente. El getMatchedCSSRules función en webkit es extremadamente meticuloso, y no he sido capaz de determinar por qué a veces funciona y lo que no en otros momentos. Por lo tanto, me gustaría evitar el uso de esta función a menos funciona 100% del tiempo. Del mismo modo, el getComputedStyle función tiene sus propios problemas. Si utilizar el inspector para cambiar el #footer elemento en esta página sea de 7px solid red en lugar de 7px solid black, el cambio se reflejará en cuando ejecuto getComputedStyle(document.getElementById('footer')).cssText en la consola, pero que también me dará un sinfín de propiedades heredadas que nunca fueron modificados por el usuario utilizando el inspector o por las hojas de estilo en la página.

Estoy en busca de una solución que funciona con webkit–compatibilidad con todos los navegadores no es un problema en el momento.

Gracias!

  • Hrmm, usted también necesita una reglas CSS reset para cuando vayas a poner el bloque de texto en algún lugar?
  • Sólo por curiosidad, ¿por qué es exactamente lo que quieres esto? Ya que dicen que se abrió el inspector de hacer un cambio, ¿desea enviar las modificaciones realizadas a la DOM a alguien, por algún tipo de aprobación? Tratando de responder al por qué en lugar de cómo podría hacer que algunos de los diferentes enfoques para su problema.
  • así, si el im iterar a través de todo el cuerpo, y tomando cada regla css, que debo recoger el css reset reglas.
  • Estoy tratando de registrar mi DOM en mobile safari para que yo pueda inspeccionar en safari en mi equipo.
  • Así que usted quiere que todos los estilos proporcionados por un regular la hoja de estilos para ser insertados en cada elemento coincidente? Como, si había <style>a { color: green; }</style> entonces que quieres es que cada a etiqueta para ver como <a style="color: green; [+ inlined styles]"></a>. ¿Por qué no simplemente copiar el <style>/<link> elementos en el encabezado?
InformationsquelleAutor D-Nice | 2011-06-02

8 Comentarios

  1. 74

    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 incluidos en el «estilo» de los atributos, excepto valores por defecto,
    y no modificar de manera permanente ese elemento.

    Por ejemplo: console.log(document.body.serializeWithStyles());

    Puede cargar este código en la Web de Inspector de línea de comandos o desde una etiqueta de secuencia de comandos en el elemento de cuerpo, pero NO en el elemento head debido a que se requiere de la existencia del documento.cuerpo.

    Lo he probado en el ordenador de sobremesa Safari 5 (no tengo la versión móvil).

    Esto funciona así:

    Para cada elemento en el DOM:

    1) el almacenamiento en caché el valor de estilo.cssText de la propiedad, lo que representa el estilo en línea, en una matriz;

    2) llamar a getComputedStyle en el elemento;

    3) verificar si tenemos el css por defecto los valores de la tabla de búsqueda correspondiente a este elemento del nombre de la etiqueta;

    4) la construcción si no;

    5) la iteración el resultado, encontrando que los valores no son por defecto el uso de la tabla de búsqueda;

    6) la aplicación de aquellos no predeterminados valores de estilo para el elemento.

    A continuación, el almacenamiento de la outerHTML como el resultado;

    Para cada elemento, la restauración de los estilos en línea de la caché;

    Volviendo a la previamente almacenada resultado.

    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;
    }
    })();
    • Gran trabajo! He probado esto en un número de diferentes páginas y es trabajado por casi todos. Voy a seguir para la prueba de esta noche, y presentarán un informe lo antes posible. Gracias!
    • Gracias por tu comentario, realmente lo aprecio! No dude en informar de errores si encuentra alguna.
    • Lo que estoy tratando de averiguar ahora es ¿por qué el error » TypeError: No se puede leer la propiedad ‘background-attachment’ undefined’ que aparece en muchas páginas. Google.com es un ejemplo. background-attachment es la primera propiedad, por orden alfabético, por lo que su probablemente bucle a través de todas las propiedades en algún lugar y buscar la propiedad en una indefinida var. he intentado añadir toneladas de comprobaciones para asegurarse de que el var no es indefinido, pero no he sido capaz de localizar el culpable todavía.
    • la adición de if ((defaultStyle && computedStyle) && computedStyle[cssPropName] !== defaultStyle[cssPropName]) elimina el error.
    • Estás en lo cierto! He probado el código en un resultado de búsqueda de Google de la página de este tiempo, y de hecho se mostró un error de tipo, defaultStyle era igual a indefinido. Lo siento, no fue un estúpido error de sintaxis en getDefaultStyleByTagName, por lo que a veces devuelve undefined. Acabo de corregir mi post.
    • Eso es bastante impresionante código. Bien vale la pena la recompensa. Me quedo con este marcador. 🙂
    • Esto es totalmente impresionante. Pero no veo por qué usted necesita para modificar el Elemento prototipo a menos que me estoy perdiendo algo. Si esto fue sólo una función que tuvo un elemento, usted podría tener esto en cualquier lugar en la página y no necesita que descargo de responsabilidad acerca de donde puede ser colocado. También la regla general es la de no modificar las cosas que no posee.
    • Estoy de acuerdo, si usted es dueño de un espacio de nombres en la página, este sería el método que mejor se ajuste a algún lugar en ese espacio de nombres. No hay problema, usted puede hacer una versión independiente de ella, ya que sólo hay un par de ocurrencias de la this palabra clave en su código. Sin embargo, por favor tenga en cuenta que la renuncia se mantenga debido a la referencia a document.body. Por cierto, sería interesante ver si se puede evitar esa restricción, aunque los guiones de carga en el head etiqueta comúnmente se desanime.
    • ¿no debería esto ser una biblioteca?
    • El respeto, el buen escribió! Gran trabajo!
    • Increíble trabajo, el hombre, sigue así.

  2. 9

    No puede usted acaba de hacer el documento.getElementsByTagName(‘cuerpo’)[0].innerHTML? Cuando hago cambios en el inspector y, a continuación, entrar en el por encima de javascript en la consola, se devuelve el HTML actualizadas.

    EDIT: acabo de intentar poner el script en una función y adjuntándolo a un evento onclick. Hecho algunos cambios en el inspector, botón pulsado, y funcionó:

    HTML

    <button onclick="printDOM()">Print DOM</button>

    Javascript

    function printDOM() {
    console.log(document.getElementsByTagName('body')[0].innerHTML) ;
    }
    • Esto funcionará para obtener todos los cambios realizados a través del inspector, pero no incluyen todos los estilos en línea desde el exterior de hojas de estilo en línea. Necesito extraer la completa DOM, incluyendo todos los estilos.
  3. 3

    En caso de que usted desea capturar toda la página, es más fácil obtener todos los no-hojas de estilo en línea y en línea de ellos.

    El enfoque en la aceptó respuesta es magnífica, pero bastante lento y toca a todo el documento.

    Tomé el siguiente enfoque para la captura de una página, incluyendo estilo:

    1. document.documentElement.outerHTML;

    2. obtener todas las hojas de estilo de la document.styleSheets API

    A lo largo de las líneas 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;
    }
    1. Agregar la captura de cssrules como el primero de la cabecera en la outerHtml texto html

    De esta manera se consigue un auto contenida de estilo de la página.

    Esta es, obviamente, menos aplicable a contenido parcial.

  4. 2

    Basado en Luc125 la respuesta, he creado un desarrollador de herramientas de extensión para Chrome que incorpora el código para la captura de los estilos y el marcado de un fragmento de página. La extensión está en el Chrome Web Store y es en Github. El «Calculada Estilos» de la opción de salida utiliza ese método.

    Extracto de la actual catedral y la impresión es como una cadena, con estilos intacto

  5. 1

    Tal vez el Google Cierre De La Biblioteca tiene una solución para usted.

    Hay código que parece hacer lo que usted necesita, es decir, para calcular las reglas CSS para reproducir la misma apariencia de un elemento fuera de su posición actual en el dom (en su caso de necesidad de que la transferencia de estilos dentro de un iframe para utilizarlo como una perfecta editor en línea).

    Citando la archivo de origen 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>
    • Que es una idea interesante, pero no he sido capaz de encontrar una manera para hacer esto satisfacer mis necesidades.
    • Los enlaces no son válidos más.
  6. 1

    OK, tal vez me estoy perdiendo algo aquí, pero no es la cadena que se desea sólo document.documentElement.innerHTML? Una prueba rápida w/Chrome comprueba que recoge los cambios realizados en las Herramientas de desarrollo para los atributos de estilo como el que usted describe. Asigna los nombres de clase no son expandido (por ejemplo, usted no tiene idea de lo class="superfuntime" está haciendo), pero si estoy leyendo tu pregunta correctamente, usted no ha declarado una necesidad.

    • Yo tendría todas las propiedades de la clase superfuntime en línea
    • Yo ingored esta en primera como trivial, sin embargo al final (después de probar otras cosas) yo finalmente llegó a la conclusión de que esto funciona simplemente genial! La mejor solución para mí! innerHTML se acaba de hacer el trabajo, innerHTML es grande, especialmente cuando un dom mento se cambió más tarde (por ejemplo, a través de js, ajax, etc).Gracias!
  7. 1

    Internet Explorer -> Herramientas del Desarrollador -> DOM Explorer

    Seleccione el elemento y haga clic derecho -> «Copiar elemento con estilos».

  8. 0

    Cromo característica de la Impresión de la DOM:

    El --dump-dom bandera imprime document.body.innerHTML a stdout:

    chrome --headless --disable-gpu --dump-dom https://www.chromestatus.com/

    Leer más

    • Esta respuesta no satisface esta parte de la solicitud: «tengan todos los estilos que actualmente se aplica a un elemento (excepto valores por defecto) y los incluyen en la línea de estilo para el elemento.»

Dejar respuesta

Please enter your comment!
Please enter your name here