当前位置: 首页 > 面试题库 >

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

呼延庆
2023-03-14
问题内容

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

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

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

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

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

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

一些注意事项:

  • 请直接使用javascript,没有像jquery这样的外部框架。
  • 更改无需再写入磁盘。
  • 更改应该是不可撤销的,或者至少是可删除的。
  • css文件中已经存在要应用的样式。
  • 它需要在iPhone 3.0及更高版本中工作。
  • 应用程序附带了所有源文件。
  • 请详细。

感谢您的任何建议。


问题答案:

我认为您要为此寻求一个完整的解决方案的要求很高,但是这似乎很有趣,因此我已经实施了它。以下内容可在最新的WebKit浏览器中使用,包括运行OS
3.0的iPhone上的Safari。它使用WebKit中存在的非标准但方便的intersectsNode方法Range,但在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">


 类似资料:
  • JavaFX:如何使用自定义样式表将文本颜色应用于TableCell? 当我直接在我的CellFactory中使用时,它工作正常,但我想使用外部CSS文件应用自定义样式。我可以证明我的CSS类已应用,因为字体变得粗体。但是,没有应用CSS文件的字体颜色。 样式表: 它在某种程度上与CSS选择器的特异性有关,但我没有设法找到任何有效的设置。 编辑:我使用CSS成功地应用了自定义文本颜色和背景颜色。我

  • 在UIWebView中调用 javascript 脚本。本demo是调用 javascript 进行百度搜索“code4app.com”。 [Code4App.com]

  • ●进入编辑地图页面—>点击打开图层管理窗口—>点样式,选择渲染方式,点"确定"保存设置。 ●文本渲染:不显示标注仅显示其标题文字,可用于在任意位置为线路、区域等添加文字说明。

  • 我需要能够更改应用于的css。如何使用javascript实现这一目标? 我的css存储为一个Javascript变量中的字符串。我不使用css文件。css由大约50个类组成,因此逐个应用它们是没有意义的。我知道如何通过更改最低类来实现这一点,但我只是想看看是否可以使用Javascript命令和变量。 伪码

  • 我试图使用python-docx模块将样式应用于文档中的段落。我可以写新的文本,但我不能对以前写的段落应用不同的风格。 以下是一个例子: 我无法从文档中判断这是否有效。这似乎表明段落样式是可写的,但是文档中没有这个用例的例子。 请让我知道这是我的问题,还是功能尚未实现。