gpt4 book ai didi

javascript - 在 uiwebview 中使用 javascript 将样式应用于文本范围

转载 作者:太空狗 更新时间:2023-10-29 13:37:28 24 4
gpt4 key购买 nike

我在 iPhone 上的 UIWebView 中将一些简单样式的文本显示为 html。它基本上是一系列段落,偶尔带有强烈或强调的短语。在运行时,我需要将样式应用于文本范围。

有几个类似的场景,其中之一是突出显示搜索结果。如果用户搜索了“某物”,我想更改出现该词后的背景颜色,然后再恢复原始背景。

是否可以使用 javascript 将样式应用于文本范围?其中的一个关键部分还在于能够取消设置样式。

似乎有两条可能的路径可循。一种方法是修改 Objective-C 中的一些 html 并将其作为某个容器的新 innerHTML 通过 javascript 传递。另一种是使用 javascript 直接操作 DOM 节点。

我可以操作 html,但在 Objective-C 中这听起来很乏味,所以如果这是一种合理的方法,我宁愿操作 DOM。我不太熟悉 javascript 和 DOM,所以我不知道这是否是一种合理的方法。

我编写了一些例程来在具有偏移量的文本范围和节点范围之间进行转换。因此,如果我从文本范围 100-200 开始,从一段开始到第三段结束,我可以获得文本节点和表示给定文本范围的节点内的偏移量。我只需要一种在文本中的偏移量处拆分文本节点的方法。目前我只是将样式应用于包含文本范围的段落。

一些注意事项:

  • 请直接使用 javascript,不要使用 jquery 等外部框架。
  • 永远不需要将更改写入磁盘。
  • 更改应该是可撤销的或至少是可移动的。
  • 要应用的样式已经存在于 css 文件中。
  • 它需要在 iPhone 3.0 及更高版本中工作。
  • 所有源文件都随应用一起提供。
  • 请详细一点。

感谢您的任何建议。

最佳答案

我认为您为此提出了很多要求以获得完整的解决方案,但它看起来很有趣,所以我已经实现了它。以下适用于最近的 WebKit 浏览器,包括运行 OS 3.0 的 iPhone 上的 Safari。它使用非标准但方便的 intersectsNode Range的方法| ,它存在于 WebKit 中,但在 3.0 中已从 Firefox 中删除,因此它在最新版本的 Firefox 中不起作用,但可以轻松实现。

以下将用 <span> 围绕每个选定的文本节点具有“someclass”类的元素以及允许轻松撤消的唯一类。 applyClassToSelection返回这个独特的类;将此类传递给 removeSpansWithClass删除跨度。

更新:解决了选择完全包含在单个文本节点中时的问题

更新 2:现已在运行 OS 3.0 的 iPhone 上进行测试和工作。

更新 3: 添加了 rangeIntersectsNode功能以添加对 Firefox 3.0 及更高版本的支持。这段代码现在应该可以在 Firefox 1.0+、Safari 3.1+、Google Chrome、Opera 9.6+ 和可能的其他操作系统(目前尚未测试)中运行。 它在 Internet Explorer 中根本不起作用,并且会在该浏览器中出错。我计划很快开发 IE 版本。

<script type="text/javascript">
var nextId = 0;

var rangeIntersectsNode = (typeof window.Range != "undefined"
&& Range.prototype.intersectsNode) ?

function(range, node) {
return range.intersectsNode(node);
} :

function(range, node) {
var nodeRange = node.ownerDocument.createRange();
try {
nodeRange.selectNode(node);
} catch (e) {
nodeRange.selectNodeContents(node);
}

return range.compareBoundaryPoints(Range.END_TO_START, nodeRange) == -1 &&
range.compareBoundaryPoints(Range.START_TO_END, nodeRange) == 1;
};

function applyClassToSelection(cssClass) {
var uniqueCssClass = "selection_" + (++nextId);
var sel = window.getSelection();
if (sel.rangeCount < 1) {
return;
}
var range = sel.getRangeAt(0);
var startNode = range.startContainer, endNode = range.endContainer;

// Split the start and end container text nodes, if necessary
if (endNode.nodeType == 3) {
endNode.splitText(range.endOffset);
range.setEnd(endNode, endNode.length);
}

if (startNode.nodeType == 3) {
startNode = startNode.splitText(range.startOffset);
range.setStart(startNode, 0);
}

// Create an array of all the text nodes in the selection
// using a TreeWalker
var containerElement = range.commonAncestorContainer;
if (containerElement.nodeType != 1) {
containerElement = containerElement.parentNode;
}

var treeWalker = document.createTreeWalker(
containerElement,
NodeFilter.SHOW_TEXT,
// Note that Range.intersectsNode is non-standard but
// implemented in WebKit
function(node) {
return rangeIntersectsNode(range, node) ?
NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
},
false
);

var selectedTextNodes = [];
while (treeWalker.nextNode()) {
selectedTextNodes.push(treeWalker.currentNode);
}

var textNode, span;

// Place each text node within range inside a <span>
// element with the desired class
for (var i = 0, len = selectedTextNodes.length; i < len; ++i) {
textNode = selectedTextNodes[i];
span = document.createElement("span");
span.className = cssClass + " " + uniqueCssClass;
textNode.parentNode.insertBefore(span, textNode);
span.appendChild(textNode);
}

return uniqueCssClass;
}

function removeSpansWithClass(cssClass) {
var spans = document.body.getElementsByClassName(cssClass),
span, parentNode;

// Convert spans to an array to prevent live updating of
// the list as we remove the spans
spans = Array.prototype.slice.call(spans, 0);

for (var i = 0, len = spans.length; i < len; ++i) {
span = spans[i];
parentNode = span.parentNode;
parentNode.insertBefore(span.firstChild, span);
parentNode.removeChild(span);

// Glue any adjacent text nodes back together
parentNode.normalize();
}
}

var c;
</script>

<input type="button" onclick="c = applyClassToSelection('someclass')"
value="Add class">
<input type="button" onclick="removeSpansWithClass(c)"
value="Remove class">

关于javascript - 在 uiwebview 中使用 javascript 将样式应用于文本范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2887101/

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