本文介绍了提取当前DOM并将其打印为字符串,样式完好无损的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要能够接受我的DOM,并将其转换为字符串。让我们说,我打开检查器,并更改一个特定元素的margin-left属性。



函数应该正确地获取当前应用于元素的所有样式(不包括默认值),并将它们包括在内联样式中



我写了一个解决方案,证明是不够的。 webkit中的 getMatchedCSSRules 函数是非常脆弱的,我不能确定为什么它有时工作,不工作其他时间。因此,我想避免使用此功能,除非它100%的时间工作。同样, getComputedStyle 函数也有自己的问题。如果使用检查器将此页面上的#footer元素更改为 7px纯红色而不是 7px纯黑色更改将反映在当我在控制台中运行 getComputedStyle(document.getElementById('footer'))。cssText ,但它也将给我一个主机的继承属性



我正在寻找一个与webkit兼容的解决方案 - 跨浏览器兼容性是不是目前的问题。



谢谢!

解决方案

我认为这可能是一个解决方案



它返回一个表示任何元素的DOM的字符串,
包含在style中的所有外部样式属性,除了默认值
,并且不会永久修改该元素。



例如: console.log(document.body。可以在Web Inspector命令行中或从主体元素中的脚本标记加载此代码,但不能在主体元素中加载此代码。头元素,因为它需要document.body的存在。



我已经测试了桌面Safari 5(我没有移动版)。



它的工作原理如下:



DOM中的每个元素:

1 )在数组中缓存表示内联样式的style.cssText属性的值;

2)在元素上调用getComputedStyle;

3)检查是否有css默认值查找表对应于此元素的标签名称;

4)如果没有则构建它;

5)遍历结果,使用查找表查找哪些值是非默认值;

6)将那些非默认样式值应用于元素。

然后存储outerHTML作为结果;

对于每个元素,恢复内联样式缓存;

返回先前存储的结果。



代码:

  Element.prototype.serializeWithStyles =(function(){

//在标签名称和css默认值查找表之间进行映射这允许在结果中排​​除默认值。
var defaultStylesByTagName = {};

//从样式表继承的样式不会为具有这些标记名称的元素呈现
var noStyleTags = {BASE:true,HEAD:true,HTML:true ,META:true,NOFRAME:true,NOSCRIPT:true,PARAM:true,SCRIPT:true,STYLE:true,TITLE:true};

//此列表确定在加载时预计算哪些css默认值查找表
//如果需要,其他标记名称的查找表将在运行时自动构建
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 ,图形,图形,图形,字体,图形,图形,DEL,DETAILS,DFN,DIV,DL,DT FOOTER,FORM,H1,H2,H3,H4,H5,H6,HEAD,HEADER,HGROUP,HR,HTML ,LEGEND,LI,LINK,MAP,LABEL,I,IFRAME,IMG,INPUT,INS MARK,MATH,MENU,META,METER,NAV,NOBR,NOSCRIPT,OBJECT,OL,OPTION,OPTGROUP,OUTPUT ,P,PARAM,PRE,PROGRESS,Q,RP,RT,RUBY,S,SAMP,SCRIPT SELECT,SMALL,SOURCE,SPAN,STRONG,STYLE,SUB,SUMMARY,SUP,SVG,TABLE,TBODY T,TRACK,U,UL,VAR,VIDEO,TAROT,TEXTAREA,TFOOT,TH,THEAD WBR];

//预计算查找表。
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< calculateStyle.length; i ++){
defaultStyle [computedStyle [i]] = calculatedStyle [computedStyle [i]];
}
document.body.removeChild(element);
return defaultStyle;
}

function getDefaultStyleByTagName(tagName){
tagName = tagName.toUpperCase();
if(!defaultStylesByTagName [tagName]){
defaultStylesByTagName [tagName] = computeDefaultStyleByTagName(tagName);
}
return defaultStylesByTagName [tagName];
}

返回函数serializeWithStyles(){
if(this.nodeType!== Node.ELEMENT_NODE){throw new TypeError(); }
var cssTexts = [];
var elements = this.querySelectorAll(*);
for(var i = 0; 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< calculateStyle.length; ii ++){
var cssPropName = calculatedStyle [ii];
if(computedStyle [cssPropName]!== defaultStyle [cssPropName]){
e.style [cssPropName] = computedStyle [cssPropName];
}
}
}
}
var result = this.outerHTML;
for(var i = 0; i elements [i] .style.cssText = cssTexts [i];
}
return result;
}
})();


I'd like to be able to take my DOM, as is, and convert it to a string. Let's say I open up the inspector and make a change to the margin-left property of a particular element. That change should be reflected in my string.

The function should properly take all the styles currently applied to an element (excluding default values) and include them in the inline style for that element.

I have written a 'solution' which has proven to be inadequate. The getMatchedCSSRules function in webkit is extremely finicky, and I haven't been able to determine why it sometimes works and doesn't work other times. Therefore, I would like to avoid using this function unless it works 100% of the time. Similarly, the getComputedStyle function has problems of its own. If use the inspector to change the #footer element on this page to be 7px solid red rather than 7px solid black, the change will be reflected in when I run getComputedStyle(document.getElementById('footer')).cssText in the console, but it will also give me a host of inherited properties that were never modified by either the user using the inspector or by the stylesheets on the page.

I am looking for a solution that works with webkit--cross browser compatibility is not an issue at the moment.

Thank you!

解决方案

I think this could be a solution (it took me nearly a whole day!).

It returns a string representing the DOM of any element,with all external styles included in the "style" attributes except default values,and does not permanently modify that element.

For example: console.log(document.body.serializeWithStyles());

You can load this code in Web Inspector command line or from a script tag in the body element but NOT in the head element because it requires the existence of document.body.

I have tested it on desktop Safari 5 (I don't have the mobile version).

It works like this:

For each element in the DOM:
1) caching the value of style.cssText property, which represents the inline style, in an array;
2) calling getComputedStyle on the element;
3) checking if we have the css default values lookup table corresponding to this element's tag name;
4) building it if not;
5) iterating through the result, finding which values are non default using the lookup table;
6) applying those non default style values to the element.
Then storing the outerHTML as the result;
For each element, restoring the inline styles from the cache;
Returning the previously stored result.

The code:

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;
    }
})();

这篇关于提取当前DOM并将其打印为字符串,样式完好无损的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 12:44
查看更多