dra*_*ard 8 html javascript css iphone uiwebview
我在iPhone上的UIWebView中显示一些简单的样式文本作为html.它基本上是一系列段落,偶尔会有强烈或强调的短语.在运行时,我需要将样式应用于文本范围.
有一些类似的场景,其中一个突出显示搜索结果.如果用户搜索了"某事",我想更改单词出现后的背景颜色,然后恢复原始背景.
是否可以使用javascript将样式应用于文本范围?其中一个关键部分也是能够取消设置风格.
似乎有两条可能的路径可供遵循.一个是修改Objective-C中的一些html并通过javascript传递它作为某个容器的新innerHTML.另一种方法是使用javascript直接操作DOM节点.
我可以操作html,但这在Objective-C中听起来很乏味,所以如果这是一种合理的方法,我宁愿操纵DOM.我不熟悉javascript和DOM,所以我不知道它是否是一种合理的方法.
我写了一些例程来在文本范围和具有偏移的节点范围之间进行转换.因此,如果我从文本范围100-200开始并且从一个段落开始到第三个结束,我可以获得文本节点和表示给定文本范围的节点内的偏移量.我只需要一种方法将文本节点拆分为文本中的偏移量.目前我只是将样式应用于包含文本范围的段落.
几点说明:
谢谢你的任何建议.
Tim*_*own 19
我认为你要求很多东西来获得一个完整的解决方案,但它似乎很有趣所以我已经实现了它.以下适用于最近的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">
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4570 次 |
| 最近记录: |