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

2024-06-29

我在 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。它使用非标准但方便intersectsNode的方法Range,它存在于 WebKit 中,但在 3.0 中从 Firefox 中删除,因此它在最新版本的 Firefox 中不起作用,但可以简单地做到这一点。

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

UPDATE:修复了选择完全包含在单个文本节点中时的问题

更新2:现已在运行 OS 3.0 的 iPhone 上测试并运行。

更新3: Added 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">
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 uiwebview 中使用 javascript 将样式应用于文本范围 的相关文章

  • 从 IE 打印时,如何防止 元素出现在多个页面上?

    我有一个 HTML 数据表 其中每个单元格可以有多行文本 打印表格时 一行可能会被分解 以便一些数据出现在第一页的底部 而一些数据出现在下一页的顶部 是否有类似于 Word 的 保持在一起 功能可以防止表格行内发生分页 我认为这将是一个常见
  • 更新主干模型/视图的轮询请求

    我需要找到一种方法来更新使用以下实现的网络应用程序backbone 用例如下 我有几个视图 每个视图 或者可能与该视图相关的模型 集合 需要在不同的时间向服务器发出不同的轮询请求以发现某些变化 我想知道最通用的方法是什么 1 实施Tradi
  • 有人知道 pinterest.com 中的 div 是如何发出的吗?

    我尝试像这样水平渲染我的 div 图像 从左到右 从上到下 但这并不完全正确 想知道是否只是垂直完成每列的渲染 从上到下 从右到左 有人知道如何模仿 复制此页面吗 更新 为了回应下面的答案 我快速搜索了 砖石与同位素 下列post http
  • UIModalTransitionStyleFlipHorizo​​ntal 横向垂直翻转

    在横向模式下 从一个视图 导航控制器堆栈的一部分 转换到另一个视图作为模态视图 并将 UIModalTransitionStyleFlipHorizo ntal 设置为 modalTransitionStyle 视图在横向模式下垂直翻转 动
  • 阻止 Firefox 在刷新后恢复先前用户输入的状态

    我有一个带有多个复选框的页面 需要表示数据库中的状态 这些复选框是 AJAX 驱动的 因此当选中一个复选框时 就会发送一个请求来更新数据库中的状态 如果他们的视图已过时 则受影响 相关复选框的视图将更新 并通知用户 并且必须重试 当我刷新时
  • 如何像这样包裹div?

    假设您有一个具有固定高度和重量的 div 在图中是最里面的一个 并且您希望周围的 div 包含它 其外边距为例如1 厘米 你会怎么做 一种方法是使用inline block显示风格 div border 1px solid blue div
  • 通过 JavaScript 传输事件来调用 :hover 伪类

    这是场景 您有两张图像 它们彼此堆叠在一起 最高阶的 z 索引图像负责处理点击事件 想想 Google 的 Map API 并且是透明的 而下面的图像负责视觉表示 这是一个伪 HTML CSS 表示 div visual container
  • 如何在 JavaScript 中将十六进制字符串转换为 Uint8Array 并返回?

    我想转换一个十六进制字符串 例如bada55 into a Uint8Array然后再回来 普通JS const fromHexString hexString gt Uint8Array from hexString match 1 2
  • 未捕获的语法错误:无法在“文档”上执行“querySelector”

  • 将画布图像保存到服务器

    我正在尝试将画布图像保存到服务器 我可以保存文件 但它始终是 0 字节 我的代码有什么问题吗 php
  • 升级到 Xcode 3.2.5 后出现“Base SDK Missing”

    所以我采取了升级到 Xcode 3 2 5 iPhone SDK 4 2 的步骤 现在我无法运行到设备 我现在总是在开发环境中看到这一点 在我当前的项目中 当进入项目设置时 我只能将 Base SDK 设置为 iOS 4 2 但这并不能改变
  • CoreGraphics 和 CoreAnimation 有什么不同?

    我正在使用 coregraphics 开发 iphone 游戏 但速度很慢 我无法玩我的游戏 所以 我用谷歌搜索了很多 在谷歌搜索过程中 我发现了以下内容 CoreGraphics CoreAnimation OpenGL ES CALay
  • 应用程序大小限制和查找应用程序的大小

    好吧 我读过无数地方说应用程序大小限制是 20 MB 有些说是 50 MB 是哪一个 更重要的是 我当前的应用程序在管理器的存档部分中的 估计应用程序商店大小 为 106 1mb 然而 当我将它分发到一个临时文件时 它会以 ipa 的形式出
  • 谷歌地图如何将图像添加到InfoWindow中

    您好 我正在尝试将图像添加到谷歌地图信息窗口中 我的代码就像这样的脚本 var ContactUs function return main function to initiate the module init function var
  • 不可能的? HTML 鼠标悬停边框颜色随边框折叠而变化?

    我希望有一个表格 其中所有边框 内部 外部 的宽度都是单个像素 我通过设置来实现这一点border collapse桌子上的风格 那么我希望onmouseover每个 TD 单元 改变border color为不同的颜色 如果表格边框尚未折
  • Visual Studio 2013 中的 JavaScript HTML5 CSS3 项目模板

    我刚刚下载了 Visual Studio 2013 Express for Web 我想知道如何部署仅限 JavaScript HTML5 和 CSS3 的项目 我找不到合适的模板或方法来做到这一点 我已经在网上搜索过JavaScript模
  • 如何在javascript中获取表中复选框的值

    我需要获取表行中提供跨度的复选框的值 下面的代码是我的项目的一部分 HTML 代码用于动态我的表格 而 javascript 代码用于获取不适用于复选框的元素的值 它适用于其他输入元素 我的桌子 var html tr class rows
  • Select2 的行为与未为 Select2 定义的 Uncaught 查询函数非常不同

    我按以下方式加载 select2 的值 声明类型 var AdjustmentType Backbone Model extend url Hexgen getContextPath referencedata adjustmenttype
  • 比较断言中的函数输出类型

    我正在努力使用 chai mocha 和 JS DOM 编写测试断言 我有一个简单的函数 例如 function HtmlElement el this element el instanceof HTMLElement el docume
  • 获取 ES6 符号的描述

    我想知道是否有一种很好的方法来获取符号的描述 例如 var s Symbol 5 toString 的默认实现将简单地打印 符号 5 我想找到一种方法来提取实际描述 即 5 Symbol description https develope

随机推荐

  • C++ 低延迟线程异步缓冲流(用于日志记录) – Boost

    Question 下面的 3 个 while 循环包含已被注释掉的代码 我搜索 TAG1 TAG2 和 TAG3 以便于识别 我只是希望 while 循环在继续操作之前等待测试的条件变为真 同时尽可能减少 CPU 资源 我首先尝试使用 Bo
  • (已弃用)片段 onOptionsItemSelected 未被调用

    EDIT 这个问题是针对已弃用的 Sherlock 操作栏的 现在应该使用 Android 支持库 我添加了一个名为 共享 的操作栏菜单选项fragment出现但没有捕获选择事件 我这样添加 Override public void onC
  • Angular 2 Spring 安全 CSRF 令牌

    大家好 我在为我的应用程序设置安全解决方案时遇到问题 所以我有一个 REST API 后端 运行在http 本地主机 51030 http localhost 51030并使用 Spring Framework 进行开发 对于前端 我有一个
  • 游戏对象跟随领导/蜈蚣问题

    我很难将一些游戏对象链接在一起以 跟随领导者 这就是我想要实现的目标 哪里有一个 头 物体并且它拉动body对象与它 就像蛇或者蜈蚣一样 然而 这就是正在发生的事情 它们都有点跟随头部 但它们似乎作为一个整体移动 谁能看到我做错了什么吗 这
  • 创建 SQLite3 表后添加 ON DELETE CASCADE 行为

    是否可以添加一个ON DELETE CASCADE创建后的表 我的架构如下 CREATE TABLE skills name varchar skill varchar level int foreign key name referenc
  • 按组连接/粘贴列并添加到原始数据

    我有一个名称数据框 名称 按 部门 分组 Dept Date Name 30 07 DEC 02 Raphaely 30 18 MAY 03 Khoo 40 07 JUN 02 Mavris 50 01 MAY 03 Kaufling 50
  • 我的重力代码应该放在 p5.js 中的哪里?

    我正在尝试为我的 p5 js 草图添加重力 但我不明白该怎么做 这是我到目前为止的代码 Jumping facing forwards stroke 100 noFill rect 220 60 50 80 noStroke fill 0
  • 如何从 Sinatra 中删除路线?

    我有一些动态加载的插件 它们在启动时注册它们的路由 但是我还需要能够在禁用它们时删除它们的路由 有没有办法删除现有的路线 API 没有任何我能找到的方法来删除它们 我能想到的唯一其他方法就是直接访问 Sinatra Base 中的 rout
  • 如何使用 python re 库分割字符串并保留分隔符?

    这是我的代码 import re string r Option A Option B Option C Option D word list re split r string gt Option A Option B Option C
  • 为了提高性能,我应该将 javascript 和 css 文件合并为一个吗? [复制]

    这个问题在这里已经有答案了 YSlow 报告表明 我在特定页面上有许多 javascript 文件 这些文件应该合并为一个 我在特定页面上有许多 css 文件 这些文件应该合并为一个 Q1 任何机构都可以详细说明这一点 如何才能快速地将它们
  • OpenGL 和多个 GPU - 一般可能性

    我想知道 是否可以在多个 GPU 上同时运行多窗口 OpenGL 应用程序 更具体地说 假设我创建了一个应用程序 其中有两个窗口 每个窗口彼此共享 GL 上下文 现在 如果我将其中一个窗口从显示器 1 在 GPU 1 上运行 移动到显示器
  • Maven 不会使用 1.7 JDK 编译 Java 7

    我一定是反对 Maven 的 因为每次我尝试使用它时 我都会花很多时间挣扎 然后就放弃了 我的最新情况是 尽管有 1 7 JDK 但我无法编译 Java 7 源代码 这是输出mvn compile 有趣的是 当我使用 Maven 3 0 4
  • 我们可以传递一个参数来查看某个类中其他类的加载情况或视图将出现吗

    抱歉 如果这不是标准问题 但现在您的解决方案可以帮助我 在我的应用程序中 我有两个类 ClassA and ClassB ClassB其中有一个表视图 我正在使用查询来填充表视图ClassB 但是我必须查询的列名是我从中得到的ClassA
  • knitr pandoc:“无法使用 pdf writer 生成 pdf 输出”

    Up front using pandoc 在knitr中 当尝试将 md或 Rmd编译为PDF时 它会抱怨 我正在简化流程可重复的研究 正如许多地方所记录的那样 我在用着pandoc and knitr并制作出色的文档 我还试图为一些不太
  • 如何使用SendInput模拟向上键按下(或其他扩展键)

    我正在尝试以编程方式模拟按下键盘上的向上箭头键以进行端到端测试 使用以下代码 GUI 控件不会接收消息 WM KEYDOWN WM GETDLGCODE WM KEYUP 我使用 Spy 来检测传入的消息 你知道为什么 你能建议另一个解决方
  • 从我的外接程序调用第 3 方 Outlook 外接程序按钮

    我正在寻找为 Outlook 创建一个插件 当邮件项目添加到某个文件夹时 它将调用另一个第 3 方插件的附加和转发功能 但是我不确定如何找到此按钮以调用它 所需的按钮显示在收件箱屏幕上 当在左下角选择邮件时 但在打开邮件 双击 时不会显示在
  • 模型形式中的值错误

    我正在使用模型表单来获取播放列表及其项目 它还包含登录脚本 我正在尝试将当前登录的用户设置为用户模型 你可以看看我之前发过的这篇文章如何避免这个下拉组合框 https stackoverflow com questions 8763612
  • 难以理解反引号内反斜杠的非明显使用

    我已经阅读了大量的页面 包括 bash 手册 但仍然发现反斜杠的 非明显 使用令人困惑 If I do echo 它打印一个星号 这是正常的 因为我转义了星号 使其成为字面意思 If I do echo 它打印 这看起来也很正常 第一个反斜
  • JSF:嵌套 ui:repeat 内的值绑定

    我有一个奇怪的问题
  • 在 uiwebview 中使用 javascript 将样式应用于文本范围

    我在 iPhone 上的 UIWebView 中将一些简单样式的文本显示为 html 它基本上是一系列段落 偶尔有强烈或强调的短语 在运行时 我需要将样式应用于文本范围 有一些类似的场景 其中之一是突出显示搜索结果 如果用户搜索了 某事 我