- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在构建一个实时 HTML 荧光笔,以便当用户选择一段文本时,该文本被具有背景属性的 span 元素包围。
这是 fiddle :https://jsfiddle.net/4hd2vrex/
问题是,当用户进行多项选择时,这会变得非常困惑,跨度会嵌套,我会得到这样的内容:
<span style="background-color: rgb(255, 255, 131);">
r
<span style="background-color: rgb(255, 255, 131);">
<span style="background-color: rgb(255, 255, 131);">
e
</span>
p
</span>
r
<span style="background-color: rgb(255, 255, 131);">
e
</span>
h
<span style="background-color: rgb(255, 255, 131);">
end
</span>
e
<span style="background-color: rgb(255, 255, 131);">
rit
</span>
</span>
神圣的大奖 bat 侠!为了解决这个问题,我有以下想法:
在添加任何 span 之前,只需将所有选定文本、span 标签和所有内容替换为原始选定文本 window.getSelection()
。
因此,例如,如果我选择了上面那堆乱七八糟的跨度,在用更多跨度包裹我选择的文本之前,我会用 window.getSelection()
替换那些跨度,这只是文本 reprehenderit 我会得到。
<span style="background-color: rgb(255, 255, 131);">reprehenderit</span>
问:如何用选择文本替换我的选择?
最佳答案
我用我的方式完成了整个高亮文本,不是使用 window.Selection API,而是使用:select(start,end).then(merge).then(filter).then(highlight)
。最有趣的是它可以高亮复杂的元素,即使是文本也不能。我发现select api也可以写一个所见即所得的html编辑器,所以我把它分享给所有对选择问题感兴趣的人,和希望能帮到你,问得好!
(function (context, factory) {
if (typeof module != 'undefined' && typeof module.exports == 'object') {
module.exports = factory(context);
} else {
factory(context, true);
}
})(window || this, function (context, bind) {
function promise(executor) {
return new Promise(executor);
}
var $TYPE = 'nodeType', $TEXT = 'textContent', $PARENT = 'parentNode', $NEXT = 'nextSibling', $FIRST = 'firstChild', NIL = {};
function leaf(node) {
return node[$TYPE] == 3;
}
function next(node, tree) {
var it = tree ? node[$FIRST] || node[$NEXT] : node[$NEXT];
if (it) {
if (leaf(it)) return it;
return next(it, true);
}
var parent = node[$PARENT];
return parent && next(parent);
}
function parent(node) {
return node[$PARENT];
}
function wrap(node, start, end) {
if (!node) throw 'node is null';
if (!leaf(node)) throw 'node is not a leaf:' + node.tagName;
var rawText = node[$TEXT];
var rawLength = rawText.length;
var self = {
node: node,
text: function (text) {
if (text !== undefined) {
node.textContent = text;
return wrap(node, 0, text.length);
}
return rawText.substring(self.start(), self.end());
},
is: function (other) {
return node == other.node;
},
start: function () {
return start === NIL || !start ? 0 : start;
},
end: function () {
return end === NIL || !end ? rawLength : end;
},
length: function () {
return self.end() - self.start();
},
to: function (end) {
return wrap(node, self.start(), end.end());
},
toLast: function () {
return wrap(node, start, rawLength);
},
next: function () {
var it = next(node);
return it && wrap(it);
},
split: function () {
if (self.length() >= rawLength) return self;
var stack = [0].concat(self.start() || []).concat(self.end()).concat(self.end() != rawLength ? rawLength : []);
var start = stack.shift();
var separated = [];
while (stack.length) {
var end = stack.shift();
var text = document.createTextNode(rawText.substring(start, end));
self.after(text);
separated.push(wrap(text));
start = end;
}
self.remove();
return !self.start() ? separated[0] : separated[1];
},
remove: function (optimized) {
var parent = node[$PARENT];
if (optimized && parent.childNodes.length == 1) {
parent[$PARENT].removeChild(parent);
}
parent.removeChild(node);
return this;
},
merge: function (other) {
var it = self.split();
return it.text(other.split().remove(true).text() + it.text());
},
after: function (e) {
node[$PARENT].insertBefore(e, node);
return this;
},
wrap: function (e) {
e.appendChild(self.split().after(e).node);
}
};
return self;
}
function select(start, end) {
return promise(function (resolve) {
start = wrap(start.text, start.offset, NIL), end = wrap(end.text, NIL, end.offset);
var selected = [];
while (start) {
if (start.is(end)) {
selected.push(start.to(end));
break;
}
selected.push(start.toLast());
start = start.next();
}
resolve(selected);
});
}
function merge(filter) {
return function (parts) {
var result = [parts.shift()];
while (parts.length) {
var prev = result.pop();
var next = parts.shift();
if (filter(prev.node, next.node)) {
result.push(next.merge(prev));
} else {
result.push(prev);
result.push(next);
}
}
return result;
}
}
function filter(test) {
return function (parts) {
return parts.filter(function (part) {
return test(part.node);
});
}
}
function apply(consume) {
return function (parts) {
return parts.forEach(function (part) {
return consume(part);
});
}
}
var exports = {
__esModule: true,
default: select,
select: select,
merge: merge,
filter: filter,
apply: apply
};
if (bind)for (var name in exports)context[name] = exports[name];
return exports;
});
(function () {
var COMPONENT_ID = 'highlight-' + +new Date;
var highlighter = {
init: function () {
this.bindEvents();
},
/**
*
*/
bindEvents: function () {
var self = this;
$('.swatch').on('click', function () {
$('.swatch').removeClass('active');
$(this).addClass('active');
});
$('.content').mouseup(function () {
var current = self.actived();
if (current.hasClass('clear')) {
self.clear();
} else {
self.highlight();
}
});
},
actived: function () {
return $('.swatch.active');
},
color: function () {
return this.actived().css('background-color');
},
/**
*
*/
highlight: function () {
var self = this;
var selection = self.getSelection();
if (selection) {
self.select(selection.getRangeAt(0)).//
then(merge(function (left, right) {
var p1 = left.parentNode;
var p2 = right.parentNode;
var a1 = self.compare(left);
var a2 = self.compare(right);
return (a1 && a2 && p1.parentNode == p2.parentNode) ||
(!a1 && !a2 && p1 == p2) ||
(a1 && !a2 && p1.parentNode == p2) ||
(!a1 && a2 && p2.parentNode == p1);
})).then(filter(function (part) {
return !self.compare(part);
})).then(function (parts) {
parts.map(function (node) {
node.wrap(self.component());
});
}).catch(function (e) {
console.log(e);
});
selection.removeAllRanges();
}
},
component: function () {
return $('<span data-toggle="' + COMPONENT_ID + '">').css('background-color', this.color()).get(0);
},
compare: function (text) {
var self = this;
var parent = $(text).parent();
var highlighted = parent.is(self.selector());
var color = parent.css('background-color');
return highlighted && color == self.color();
},
selector: function () {
return '[data-toggle="?"]'.replace(/\?/, COMPONENT_ID);
},
clear: function () {
var self = this;
var selection = self.getSelection();
if (selection) {
self.select(selection.getRangeAt(0)).then(apply(function (part) {
var text = $(part.split().node);
while (true) {
var comp = text.closest(self.selector());
if (!comp || !comp.length) {
break;
}
var children = comp.contents();
var first = children[0], last = children[children.length - 1];
if (text.is(last)) {
comp.after(text);
} else if (text.is(first)) {
comp.before(text);
} else {
var heading = comp.clone().empty();
for (var i = 0; i < children.length; i++) {
if (text.is(children[i])) {
break;
}
heading.append(children[i]);
}
comp.before(heading).before(text);
}
if (first == last) comp.remove();
}
}));
selection.removeAllRanges();
}
},
select: function (range) {
return select(
{text: range.startContainer, offset: range.startOffset},
{text: range.endContainer, offset: range.endOffset}
);
},
getSelection: function () {
var sel = window.getSelection();
return /^\s*$/.test(self && sel.toString()) ? null : sel;
}
};
highlighter.init();
})();
body {
margin: 0;
background: #fafafa;
box-shadow: 0 0 5rem rgba(0, 0, 0, 0.25) inset;
}
::-moz-selection {
background-color: rgba(0, 0, 0, 0.2);
}
::selection {
background-color: rgba(0, 0, 0, 0.2);
}
.content {
padding: 100px;
}
.footer {
padding: 0 100px 0 100px;
flex-basis: 100%;
height: 60px;
background: #292B2C;
position:fixed;top:0;width:100%;
}
.footer .items-left {
float: left;
}
.footer-item {
line-height: 60px;
}
#colors {
padding: 12px;
}
.swatch {
width: 30px;
height: 30px;
border-radius: 15px;
box-shadow: inset 0px 1px 0px rgba(255, 255, 255, 0.5), 0px 2px 2px rgba(0, 0, 0, 0.5);
display: inline-block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="content">
<span style="color:red;"><b>Content</b> <i>Lorem</i> <font size='7'>ipsum</font> dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim</span> veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum.
Content Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum.
Content Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum.
Content Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est
laborum.
</div>
<div class="footer">
<div class="items-left">
<div id="colors">
<div class="swatch active" style="background-color: rgba(255,255,131,.5);"></div>
<div class="swatch" style="background-color: rgba(255,140,218,.5);"></div>
<div class="swatch" style="background-color: rgba(144,255,184,.5);"></div>
<div class="swatch clear"></div>
</div>
</div>
</div>
关于javascript - 替换 mouseup 上的选定文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42599812/
我想对一个字符串执行搜索和替换,比如 password。 正如您从问题中了解到的那样,替换后的字符串应变为 sdvvzrug。 但不幸的是,下面的代码输出bbbbcaab: $search = ran
我正在使用 futurize --stage2它应用了许多源代码转换以使代码 python2 和 python3 兼容。其中一个修复是所有分区 a/b 都替换为 old_div(a/b),我想避免这种
我正在使用 RStudio,但我在控制台上的输出被截断了。我找不到如何停止截断(我尝试搜索 ?options 以及在谷歌上搜索的时间比我想承认的要长)。 编辑:我向大家道歉!我最初的长名称为“This
我有一个 fragment 堆栈,我在其中使用替换和相加。添加或替换我的 fragment 的代码(在我的 Activity 中)如下 private fun addFragment(fragment
我在一个数组中插入了一些字符串,但在我这样做之前,我想按照主题所说的去做。只用 %20 替换空格,我这样做: Name.push(linkText.replace(" ", "%20")); 但是我如
我正在尝试编译和测试我在网上看到的代码 Expanding an IP add 。但是,当我尝试编译它时,我收到有关 StringBuilder 替换方法的错误。它说: IPadd.java:52:
我正在尝试使用 dplyr 的最新功能重写我的部分代码,方法是将 data.frame() 替换为 data_frame() 和 cbind() 与 bind_cols(): library(rgeo
我最近偶然发现了 replace()和 "[ x.tst s.tst s.tst [,1] [,2] [,3] [1,] 0 0 0
我一直想知道,如何在给定的参数内进行替换。 如果你有这样的一行: 123,Hello,World,(I am, here), unknown 你想更换 World与 Foobar那么这是一个简单的任务
如何转义字符串中的双引号?例如, input: "Nobody" output: \"Nobody\" 我尝试过这样的操作,但不起作用: String name = "Nobody"; name.r
我正在做类似的事情: SQL sql sQl SqL var ps = document.getElementsByTagName('p'); for(var i = 0; i 但它不会替换文本。
我正在尝试用 \" 替换所有 " 并用 JSON 解析字符串,但浏览器抛出错误 SyntaxError: JSON Parse error: Unrecognized token '\'. 下面是代码
大家好,在这里挣扎...... 是否可以将第一个正斜杠之间的任何内容替换为“”,但保留其余部分? 例如var 将是 string "/anything-here-this-needs-to-be-re
在下面的代码中,JavaScript 替换函数中的 alert(a) 将提醒匹配的字符串,在本例中,将是 {name} 和 {place}。 这按照文档 javascript docs 的描述工作,即
+-----------------------------+ | tables | +-------------------
我正在尝试用\"替换包含 "的字符串,下面是我尝试过的程序 String s="\"/test /string\""; s = s.replaceAll("\"", "\\\"");
var text = "a's ..a's ...\"... "; text = convert(text); function convert( text ) { var n = text
我正在尝试使用 JavaScript 中的替换函数,但有一个问题。 strNewDdlVolCannRegion = strNewDdlVolCannRegion.replace(/_existing
好吧,首先我对我的上一篇文章感到非常抱歉,但我真的需要帮助,我会把我真正想要的东西放在一个更清晰的代码中。我不擅长 javascript,所以希望你能帮助我。
我正在写一张纸条,遇到了障碍。可能有更有效的方法来执行此操作,但我对 Python 还很陌生。我正在尝试创建用户生成的 IP 地址列表。我正在使用 print 来查看生成的值是否正确。当我运行此代码时
我是一名优秀的程序员,十分优秀!