gpt4 book ai didi

javascript - 替换 mouseup 上的选定文本

转载 作者:行者123 更新时间:2023-11-27 23:17:01 24 4
gpt4 key购买 nike

我正在构建一个实时 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com