【问题标题】:Outline any block of content on a web page概述网页上的任何内容块
【发布时间】:2015-09-19 06:08:55
【问题描述】:

目前在我们正在构建的 web cms 中,我们允许用户包含任意内容(无论是纯文本还是任何 html 内容)以显示在网站的任何部分。这些块称为小部件(显然,出于安全目的,我们会采取措施清理它们)。

我希望能够在必要时突出显示这些块以进行调试,但是我不能将它们包装在任何其他元素(例如 div)中,因为它可能会破坏布局。我在这个网站上发现了几个问题,对同一个问题进行了重新评分,但还没有任何好的解决方案。

如果我们被允许使用某种非布局元素(例如评论标签)来包裹内容块以能够执行一些操作(例如像这样突出显示),那就太好了,但我没有找到任何方法来做到这一点。

我对任何解决方案(js、基于服务器等)都很满意,只要它允许我在不破坏布局的情况下勾勒出任何内容块。如果您有任何建议,请告诉我。

小部件内容的几个示例:

纯文本小部件:

this is a the content of text only widget, there is also no wrapper here.

HTML 小部件:

<h1>Hello world </h1>

<section class="content">
    The problem here is that we do not want to force the users to 
    always wrap their contents inside a root element.
    In this example you can see that the content contains 1 h1 element
    and 1 section element. To outline this whole widget we may need to 
    wrap it by an outer element which may break the layout.
</section>

【问题讨论】:

  • 您如何识别它们以进行清理?

标签: javascript html css


【解决方案1】:

这不是您想要的,但它可能已经足够接近 (fiddle)。该脚本将使用&lt;span class="highlight"&gt; 包装小部件。跨度不应以任何方式影响布局:

.highlight {
    display: block; // this will change the layout as it inserts a line break
    outline: 1px dashed red;
}

渲染 html 时,在 widget 前后添加注释:

<!--!!!start widget!!!-->
this is a the content of text only widget, there is also no wrapper here.
<!--!!!end widget!!!-->

当您进入调试模式时,运行此脚本以添加高亮范围:

var START_WIDGET = '!!!start widget!!!';
var END_WIDGET = '!!!end widget!!!';

function filter( node ) {
    if ( node.nodeValue !== START_WIDGET && node.nodeValue !== END_WIDGET) { // filter all comment nodes that are not start or end widget
        return( NodeFilter.FILTER_SKIP );
    }
    return( NodeFilter.FILTER_ACCEPT );
}

filter.acceptNode = filter;

var treeWalker = document.createTreeWalker(
    document.body,
    NodeFilter.SHOW_COMMENT,
    filter,
    false
);

var start = null;

while ( treeWalker.nextNode() ) {
    if(treeWalker.currentNode.nodeValue === START_WIDGET) {
         start = treeWalker.currentNode;
    } else if(treeWalker.currentNode.nodeValue === END_WIDGET) {
        highlight(start, treeWalker.currentNode);
        start = null;
    }
}

function highlight(start, end) {
    var currentNode = start.nextSibling;
    var span = document.createElement('span');
    var temp;

    span.className = 'highlight';

    while(currentNode !== end) {
        temp = currentNode;
        currentNode = currentNode.nextSibling;
        span.appendChild(temp);
    }

    $(span).insertAfter(start);
}

treeWalker 代码基于这篇文章 - Finding HTML Comment Nodes In The DOM Using TreeWalker

【讨论】:

  • 我喜欢这个想法,但不能保证小部件将被包裹在任何元素中(例如,小部件可以是纯文本小部件),或者内容可能包含多个元素而没有根。我会在这个问题上添加一些例子。
  • 每个小部件内容都应该通过表单输入,我们在插入数据库之前去除危险的javascript标签等。当我们渲染小部件时,我们会从数据库内容中打印出来。
  • 在调试模式下,我们可以包装元素,即使布局可能会发生一些变化?
  • 这是可能的,但这是我想尝试的最后手段,因为我想尽可能保持布局完整。
  • 几乎完美,我想我发现当我们在fiddle.jshell.net/gbxzh4uL/6 中混合了流氓纯文本时会发生问题,我将尝试调试 js 并找出原因。
【解决方案2】:

试试 style 属性,outline。就像border,但它的大小不会影响布局。将您的小部件包裹在 &lt;span&gt;s 中,因为它们是内联元素,如果您不想破坏您的布局,这会使它们变得完美。除了使用outline&lt;span&gt; 之外,您还可以使用defaults 来促进平滑均匀的布局。

CSS

/* DEFAULTS */

html {
  box-sizing: border-box;
  font: 400 16px/1.45'Source Code Pro';
}
*,
*:before,
*:after {
  box-sizing: inherit;
  margin: 0;
  padding: 0;
  border: 0 solid transparent;
}
/* WIDGETS */

.widget {
  outline: 3px dashed orange;
}
.widget.text {
  outline: 1px solid blue;
}
.widget.html {
  outline: 1px solid red;
}
.widget.html > .content {
  outline: 1px solid black;
  background: yellow;
}
<span class="widget text">
this is a the content of text only widget, there is also no wrapper here.
</span>
<span class="widget html">
<h1>Hello world</h1>

<section class="content">
    The problem here is that we do not want to force the users to 
    always wrap their contents inside a root element.
    In this example you can see that the content contains 1 h1 element
    and 1 section element. To outline this whole widget we may need to 
    wrap it by an outer element which may break the layout.
</section>
  </span>

【讨论】:

  • 非常感谢您的回答,Ori Dori 首先添加了他的答案,这很相似,所以我将他的答案标记为“答案”。最好的。
  • 很高兴您找到了解决方案。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-21
  • 1970-01-01
  • 1970-01-01
  • 2014-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多