好的,随后会有更多测试。当我使用虚假间隔时,看起来代码工作正常,但正则表达式最终失败。具体而言,以下方案有效:
a
标记a
标记a
标记a
标记以下情况不起作用:
a
标记上方的一行/多行,然后选择a
代码当“不起作用”时会发生什么,它会从DOM中删除a
标记spacer。这可能是正则表达式的问题......
基本,当您选择a
标记周围的文字时,它会失败。
我不需要在p
标记中包含每一行,而是可以使用内联元素,例如a
,span
或label
标记,display:inline-block
和高度+宽度作为新的线元素(<br />
)。这应该可以更容易地修改代码,因为唯一需要更改的部分是我在文本之间获取文本。我只需要更改该部分selectedText.textContent
,以检索也在边界内的HTML而不仅仅是文本。
我正在创建一个要求用户选择文字的Phonegap。但是,我需要对文本选择进行精细控制,并且无法再将整个文本内容放在pre
样式的p
标记中。相反,我需要使用类似<a class="space"></a>
的代码表示换行符,以便可以精确突出显示正确的单词。当我的文字看起来像这样:
<p class="text">This is line one
Line two
Line three
</p>
并且有.text{ white-space:pre-wrap }
,以下代码允许我选择单词,然后用span
元素包装文本以显示文本突出显示:
$("p").on("copy", highlight);
function highlight() {
var text = window.getSelection().toString();
var selection = window.getSelection().getRangeAt(0);
var selectedText = selection.extractContents();
var span = $("<span class='highlight'>" + selectedText.textContent + "</span>");
selection.insertNode(span[0]);
if (selectedText.childNodes[1] != undefined) {
$(selectedText.childNodes[1]).remove();
}
var txt = $('.text').html();
$('.text').html(txt.replace(/<\/span>(?:\s)*<span class="highlight">/g, ''));
$(".output ul").html("");
$(".text .highlight").each(function () {
$(".output ul").append("<li>" + $(this).text() + "</li>");
});
clearSelection();
}
function clearSelection() {
if (document.selection) {
document.selection.empty();
} else if (window.getSelection) {
window.getSelection().removeAllRanges();
}
}
此代码可以很好地工作,但不是每行都用spacer标记分隔。新文本如下:
<p class="text">
Line one
<a class="space"></a>
Line two
<a class="space"></a>
Line three
</p>
当我修改上面的代码以使用由<a class="space"></a>
表示的新行时,代码失败。它只检索选择的文本,而不是HTML(selectedText.textContent
)。我不确定正则表达式是否也会因a
元素作为新行而失败。 a
元素可以是span
或label
,也可以是任何正常的内联定位元素,以诱骗iOS允许我选择字母而不是块元素。
是否有更改代码以保留新的线元素?
如果突出显示“第一行”文字:
<p class="text">
<span class="highlight">Line one</span>
<a class="space"></a>
Line two
<a class="space"></a>
Line three
</p>
如果突出显示“第一行第二行”文本:
<p class="text">
<span class="highlight">Line one
<a class="space"></a>
Line two</span>
<a class="space"></a>
Line three
</p>
当然,不同的部分和单个字母也可以突出显示,而不是全行。
答案 0 :(得分:0)
这是一个支持您要求的所有功能的解决方案:
<强> HTML 强>:
<p class="text">
First Line
<a class="space"></a>
<a class="space"></a>
Second Line
<span class="space"></span>
Third Line
<label class="space"></label>
Forth Line
</p>
<ul class="output"></ul>
<强> CSS 强>:
.space {
display: inline-block;
width: 100%;
}
.highlighting {
background-color: green;
}
<强>的JavaScript 强>:
var text,
output,
unwrapContents,
mergeElements,
clearSelection,
clearHighlighting,
mergeHighlighting,
handleCopy;
unwrapContents = function unwrapContents(element) {
while(element.firstChild !== null) {
element.parentNode.insertBefore(element.firstChild, element);
}
element.parentNode.removeChild(element);
};
mergeElements = function mergeElements(startElement, endElement) {
var currentElement;
endElement = endElement.nextSibling;
while((currentElement = startElement.nextSibling) !== endElement) {
startElement.appendChild(currentElement);
}
};
clearSelection = function clearSelection() {
if (document.selection) {
document.selection.empty();
} else if (window.getSelection) {
window.getSelection().removeAllRanges();
}
};
clearHighlighting = function clearHighlighting(target, exception) {
$('.highlighting', target).each(function(index, highlighting) {
if(highlighting !== exception) {
unwrapContents(highlighting);
}
});
target.normalize();
};
mergeHighlighting = function mergeHighlighting() {
var i, j;
// Remove internal highlights
$('.highlighting', text).filter(function() {
return this.parentNode.className === 'highlighting';
}).each(function(index, highlighting) {
unwrapContents(highlighting);
});
text.normalize();
// Merge adjacent highlights
first:
for(i=0; i<text.childNodes.length-1; i++) {
if(text.childNodes[i].className === 'highlighting') {
for(j=i+1; j<text.childNodes.length; j++) {
if(text.childNodes[j].className === 'highlighting') {
mergeElements(text.childNodes[i], text.childNodes[j--]);
unwrapContents(text.childNodes[i].lastChild);
} else {
switch(text.childNodes[j].nodeType) {
case 1:
if(text.childNodes[j].className !== 'space') {
continue first;
}
break;
case 3:
if(text.childNodes[j].textContent.trim() !== '') {
continue first;
}
break;
}
}
}
}
}
};
handleCopy = function handleCopy() {
var range,
highlighting,
item;
// Highlighting
range = window.getSelection().getRangeAt(0);
highlighting = document.createElement('span');
highlighting.className = 'highlighting';
highlighting.appendChild(range.cloneContents());
range.deleteContents();
range.insertNode(highlighting);
// Output
item = document.createElement('li');
item.innerHTML = highlighting.innerHTML;
clearHighlighting(item);
output.appendChild(item);
// Cleanup
mergeHighlighting();
clearSelection();
};
$(function(){
text = $('.text')[0];
output = $('.output')[0];
$(text).on('copy', handleCopy);
});
以下是一个工作示例http://jsbin.com/efohit/3/edit
答案 1 :(得分:-1)
好吧,我想出了一个解决方案,也很简单。
如果.text
看起来像这样:
<p class="text">Line one
<a class="space"></a>Line two
<a class="space"></a>Line three</p>
使用上面的确切标记和换行符,然后我可以找到每个\n
并用间隔元素替换它。
if (textStr.indexOf("\n") >= 0) {
textStr = textStr.replace(/\n/g, "\n<a class='space'></a>");
}
这根本不是多功能的,如果有多个换行符,如果标签不同等,则会失败。所以,我鼓励任何有更好方法的人回答这个问题!它没那么难,我想通了。