- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在 iPhone 上的 UIWebView 中将一些简单样式的文本显示为 html。它基本上是一系列段落,偶尔带有强烈或强调的短语。在运行时,我需要将样式应用于文本范围。
有几个类似的场景,其中之一是突出显示搜索结果。如果用户搜索了“某物”,我想更改出现该词后的背景颜色,然后再恢复原始背景。
是否可以使用 javascript 将样式应用于文本范围?其中的一个关键部分还在于能够取消设置样式。
似乎有两条可能的路径可循。一种方法是修改 Objective-C 中的一些 html 并将其作为某个容器的新 innerHTML 通过 javascript 传递。另一种是使用 javascript 直接操作 DOM 节点。
我可以操作 html,但在 Objective-C 中这听起来很乏味,所以如果这是一种合理的方法,我宁愿操作 DOM。我不太熟悉 javascript 和 DOM,所以我不知道这是否是一种合理的方法。
我编写了一些例程来在具有偏移量的文本范围和节点范围之间进行转换。因此,如果我从文本范围 100-200 开始,从一段开始到第三段结束,我可以获得文本节点和表示给定文本范围的节点内的偏移量。我只需要一种在文本中的偏移量处拆分文本节点的方法。目前我只是将样式应用于包含文本范围的段落。
一些注意事项:
感谢您的任何建议。
最佳答案
我认为您为此提出了很多要求以获得完整的解决方案,但它看起来很有趣,所以我已经实现了它。以下适用于最近的 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/
我不能解决这个问题。和标题说的差不多…… 如果其他两个范围/列中有“否”,我如何获得范围或列的平均值? 换句话说,我想计算 A 列的平均值,并且我有两列询问是/否问题(B 列和 C 列)。我只希望 B
我知道 python 2to3 将所有 xrange 更改为 range 我没有发现任何问题。我的问题是关于它如何将 range(...) 更改为 list(range(...)) :它是愚蠢的,只是
我有一个 Primefaces JSF 项目,并且我的 Bean 注释有以下内容: @Named("reportTabBean") @SessionScoped public class Report
在 rails3 中,我在模型中制作了相同的范围。例如 class Common ?" , at) } end 我想将公共(public)范围拆分为 lib 中的模块。所以我试试这个。 module
我需要在另一个 View 范围 bean 中使用保存在 View 范围 bean 中的一些数据。 @ManagedBean @ViewScoped public class Attivita impl
为什么下面的代码输出4?谁能给我推荐一篇好文章来深入学习 javascript 范围。 这段代码返回4,但我不明白为什么? (function f(){ return f(); functio
我有一个与此结构类似的脚本 $(function(){ var someVariable; function doSomething(){ //here } $('#som
我刚刚开始学习 Jquery,但这些示例对我帮助不大...... 现在,以下代码发生的情况是,我有 4 个表单,我使用每个表单的链接在它们之间进行切换。但我不知道如何在第一个函数中获取变量“postO
为什么当我这样做时: function Dog(){ this.firstName = 'scrappy'; } Dog.firstName 未定义? 但是我可以这样做: Dog.firstNa
我想打印文本文件 text.txt 的选定部分,其中包含: tickme 1.1(no.3) lesson1-bases lesson2-advancedfurther para:using the
我正在编写一些 JavaScript 代码。我对这个关键字有点困惑。如何在 dataReceivedHandler 函数中访问 logger 变量? MyClass: { logger: nu
我有这个代码: Public Sub test() Dim Tgt As Range Set Tgt = Range("A1") End Sub 我想更改当前为“A1”的 Tgt 的引
我正忙于此工作,以为我会把它放在我们那里。 该数字必须是最多3个单位和最多5个小数位的数字,等等。 有效的 999.99999 99.9 9 0.99999 0 无效的 -0.1 999.123456
覆盖代码时: @Override public void open(ExecutionContext executionContext) { super.open(executio
我想使用 preg_match 来匹配数字 1 - 21。我如何使用 preg_match 来做到这一点?如果数字大于 21,我不想匹配任何东西。 example preg_match('([0-9]
根据docs range函数有四种形式: (range) 0 - 无穷大 (range end) 0 - 结束 (range start end)开始 - 结束 (range start end st
我知道有一个UISlider,但是有人已经制作了RangeSlider(用两个拇指吗?)或者知道如何扩展 uislider? 最佳答案 我认为你不能直接扩展 UISlider,你可能需要扩展 UICo
我正在尝试将范围转换为列表。 nums = [] for x in range (9000, 9004): nums.append(x) print nums 输出 [9000] [9
请注意:此问题是由于在运行我的修饰方法时使用了GraphQL解析器。这意味着this的范围为undefined。但是,该问题的基础知识对于装饰者遇到问题的任何人都是有用的。 这是我想使用的基本装饰器(
我正在尝试创建一个工具来从网页上抓取信息(是的,我有权限)。 到目前为止,我一直在使用 Node.js 结合 requests 和 Cheerio 来拉取页面,然后根据 CSS 选择器查找信息。我已经
我是一名优秀的程序员,十分优秀!