使用 JavaScript 让 XForms 变得更健壮

登录342

登录342

2016-02-19 17:11

清醒时做事,糊涂时读书,大怒时睡觉,无聊时关注图老师为大家准备的精彩内容。下面为大家推荐使用 JavaScript 让 XForms 变得更健壮,无聊中的都看过来。

  先决条件

  本文只基于 XForms 和 JavaScript。针对安装在 Mozilla Firefox 2.0 之上的 Mozilla XForms 插件 进行测试。使用的是标准的 XForms 和 JavaScript,因此应该在这两个标准技术的其他实现上运行。没有使用服务器端的技术。

  典型的表示例

  我们来看一个典型的 XForms 示例。它展示了如何创建表示 XML 文档中重复节点的表。尤其展示了如何使用 XForms 执行聚集计算以及如何使用 XForms 添加或删除模型数据的节点,同步地自动保存视图。查看清单 1 中的完整源代码。

  清单 1. 典型的 XForms 表示例

?xml version="1.0" encoding="UTF-8"?xhtml:html xmlns:ev="http://www.w3.org/2001/xml-events"xmlns:xforms="http://www.w3.org/2002/xforms"xmlns:xhtml="http://www.w3.org/1999/xhtml"xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xhtml:head    xhtml:titleDemonstration of table with                   column total/xhtml:title    xf:model id="my-model" xmlns="http://www.w3.org/1999/xhtml"xmlns:xf="http://www.w3.org/2002/xforms"      xf:instance id="my-data" src="my-data.xml" xmlns=""/      xf:bind calculate="sum(../Item/Amount)" nodeset="/Data/Total"/      xf:submission action="my-data.xml" id="update-from-local-file"instance="my-data" method="get" replace="instance"/      xf:submission action="my-data.xml" id="view-xml-instance"method="get"/      xf:submission action="my-data.xml" id="save-to-local-file"method="put"/    /xf:model  /xhtml:head  xhtml:body    xf:group ref="/Data" xmlns="http://www.w3.org/1999/xhtml"xmlns:xf="http://www.w3.org/2002/xforms"      xf:label/      xf:repeat id="repeatItem" nodeset="Item"xmlns="http://www.w3.org/1999/xhtml"        xf:input class="item-description" id="description-input"ref="Description" xmlns="http://www.w3.org/1999/xhtml"          xf:label/        /xf:input        xf:input class="item-amount" ref="Amount"xmlns="http://www.w3.org/1999/xhtml"          xf:label/        /xf:input      /xf:repeat      xhtml:div id="sum"      xf:output ref="/Data/Total" xmlns="http://www.w3.org/1999/xhtml"        xf:label/      /xf:output      /xhtml:div      xf:trigger id="insertbutton" xmlns="http://www.w3.org/1999/xhtml"        xf:labelAdd Item/xf:label        xf:action ev:event="DOMActivate"          xf:insert at="last()" nodeset="Item[last()]"position="after"/          xf:setvalue ref="Item[last()]/Description" value="''"/          xf:setvalue ref="Item[last()]/Amount" value="0"/          xf:setfocus control="description-input"/        /xf:action      /xf:trigger      xf:trigger id="delete" xmlns="http://www.w3.org/1999/xhtml"        xf:labelDelete Item/xf:label        xf:delete at="index('repeatItem')" ev:event="DOMActivate"nodeset="Item[index('repeatItem')]"/      /xf:trigger      xf:submit submission="update-from-local-file"xmlns="http://www.w3.org/1999/xhtml"        xf:labelReload/xf:label      /xf:submit      xf:submit submission="save-to-local-file"xmlns="http://www.w3.org/1999/xhtml"        xf:labelSave/xf:label      /xf:submit      xf:submit submission="view-xml-instance"xmlns="http://www.w3.org/1999/xhtml"        xf:labelView XML Instance/xf:label      /xf:submit    /xf:group  /xhtml:body/xhtml:html

本文示例代码或素材下载

  您可能注意到了,在源代码中模型中的数据来自外部 XML 文件。该文件如清单 2 所示。

  清单 2. 示例的 XML 数据

?xml version="1.0" encoding="UTF-8"?Data  Item   DescriptionFurniture/Description   Amount1000/Amount  /Item  Item   DescriptionDock/Description   Amount2000/Amount  /Item  Item   DescriptionBoat/Description   Amount3000/Amount  /Item  Item   DescriptionLawn equipment/Description   Amount4000/Amount  /Item  Item   DescriptionHot tub/Description   Amount5000/Amount  /Item  Total15000/Total/Data

  运行示例

  简单地在 Web 浏览器中打开示例即可运行它。您应该看到类似图 1 所示的内容。

  图 1. 典型的 XForms 示例

  

  尝试此示例,注意,您可以使用显示的 Add Item 和 Delete Item 按钮添加和删除行。例如,如果您单击一次 Delete Item 按钮,您应看到类似图 2 的内容。

  图 2. 删除了一个项目

  

  注意,不仅是删除了顶部的项目,而且项目总数也重新进行了计算。这很好地说明了 XForms 的强大功能。再单击 Delete Item 按钮四次,您应看到类似图 3 的内容。

  图 3. 删除了所有项目

  

  这不怎么好看,但是可以单击 Add Item 按钮开始重新输入数据,对吧?但结果是在这种情况下单击 Add Item 按钮不起任何作用。

  问题出在哪儿?

  为什么 Add Item 在这种情况下不起作用?如果您查看 源代码,Add Item 按钮导致向模型中进行插入,使用 XForms 插入命令添加一条记录。而那条记录刚好是一个 Item 节点,因此 Add Item 操作接着为 Item 的 Description 和 Amount 节点设置一些默认值。Add Item 通过实际上克隆结构中的最后一个节点以定义插入节点的类型。nodeset="Item[last()]" 正是实现此操作。这正是 bug 的

  下面介绍其工作原理。您需要从 JavaScript 中访问 XForms 模型。所幸的是,使用 JavaScript 的 DOM API 即可轻松地实现访问。XForms 模型是页面 DOM 的一部分,因此您只需使用 document.getElementById() 方法,正如您访问 HTML div 或 HTML 输入字段那样。

  当您使用 document.getElementById() 访问 XForms 模型时,如 清单 3 所示,您得到的是 nsIXFormsModelElement。此对象中含有几个非常有用的方法,包括上面使用的 getInstanceDocument() 方法。这样您就可以访问 清单 1 中定义的 XForms 实例。这是一个 DOM 对象,表示 清单 2 中的 XML 文档。因此在 JavaScript 代码中,您只需让 DOM 获取 Item 元素即可。您确定模型中有多少个 Item 并将其存储在 cnt 变量中。很明显,此处要处理两个用例。第一个是您拥有不止一个 Item,第二个是您只有一个 Item。在第一个用例中,您需要删除项目。

  使用 JavaScript 删除项目

  那么如何使用 JavaScript 而不是 XForms 删除控件删除一条 Item 记录呢?解决方案极其简单。先前调用的 getInstanceDocument() 方法给您提供一个真正的 DOM 对象。因此您可以对此对象执行任何对其他 DOM 对象执行的操作。它支持全部的 DOM API 功能。因此您简单地对 DOM 元素使用 removeChild() 方法。删除 index (cnt - 1) 处的 Item,因为您的元素数组(调用 getElementsByTagName("Item") 获得)是 0-indexed。这里没有什么神奇的 XForms API,只有简单的 DOM 编程。

  删除最后一个项目

  您已经重新生成了使用 XForms 删除命令能够正常完成的逻辑。这样做的目的是为了更优雅地处理删除最后一个项目时的情况。现在查看一下这个临界情况,比如 cnt == 1。

  正如前面提到的,此处的关键在于您并不希望实际删除最后一个项目。如果删除,则 Add Item 动作中的 XForms 插入命令将不再有效。当然,您也可以重新编码,但是尽量避免这样做。

  因此不是删除最后一个项目,而是使用一个空白 Item 替代该项目的内容。这个 Item 的类型与您单击 Add Item 按钮时得到的 Item 类型相同。例如,它的 Description 为一个空字符串,而它的 Amount 为 0。为此,您再次使用 DOM API。您只访问最后一个 Item 元素,然后访问该元素的 Description 和 Amount 元素。我们将其文本节点的值分别设为空字符串和 0。

  让视图和模型同步

  此时,您已经处理了 Delete Item 的两个用例。还有一点工作要做。通常情况下,当您使用 XForms 命令修改 XForms 模型时,所有的重新计算和视图刷新都是自动完成的。使用 JavaScript 访问这些内容时情况却并非如此。您需要手动完成这些工作。

  所幸的是,在 deleteItem() 函数开始部分,您引用的 nsIXFormsModelElement 对象含有几个有用的方法可以帮助解决问题。首先使用的是它的 rebuild() 方法。此方法让它重建模型中数据的内部表示。它实际上让模型对象与 DOM 同步。这完全不会影响视图,只是对模型有影响。

  接下来您需要使用模型的 recalculate() 方法。原因在于您要使用模型中的 XForms bind-calculate 命令跟踪表中 amount 的总数。当您调用 recalculate() 方法时会刷新该计算。通用,这只是让模型与 DOM 同步。完全不影响视图。

  既然模型和数据已经同步了,您可以重新绘制视图。为此,您对模型调用 refresh() 方法。此方法导致绑定到模型的所有控件被刷新。对于删除一行而言,这将使该行消失,对于删除最后一行,这将导致最后一行的数据更改为指定的空白数据。在这两种情况下,这将使显示的项目总数基于当前数据得到更新。

  触发 JavaScript

  既然已经编写了智能的 JavaScript 函数处理删除,只需修改 XForm,使它在调用到 Delete Item 按钮时调用此 JavaScript 就可大功告成了。为此,只需修改 Delete Item 的 XForms 声明,如清单 4 所示。

  清单 4. 新的 XForm delete item 控件

xf:trigger id="delete" xmlns="http://www.w3.org/1999/xhtml"        xf:labelDelete Item/xf:label        xf:load ev:event="DOMActivate"resource="javascript:deleteItem()"/      /xf:trigger

  注意,您只是将 XForms delete 命令替换为引用 deleteItem() JavaScript 函数的 load 命令。这是最后一个需要修改的地方。现在我们来运行一下修改后的示例。

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)

  运行修改后的示例

  简单地将示例加载到浏览器中。显示的内容与 图 1 中原来显示的一样。但是,当您删除至最后一行并单击 Delete Item 后,您应看到图 4 所示的结果。

  图 4. 删除最后一行

  

  现在最后一行没有消失。而是变为默认值。如果单击 Add Item 按钮,您将看见类似图 5 的内容。

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)

  图 5. 删除最后一个 Item 后添加 Item

  

  Add Item 按钮仍然有效,没有什么变化。

  您已经了解了如何使用 JavaScript 创建更智能的 delete item 动作。更重要的是,您了解了如何使用 JavaScript 访问和修改 XForms 模型数据,重新计算 XForms 绑定的计算,以及刷新 XForms 视图。您可以想像几种其他方法,使 Add Item 和 Delete Item 动作提供越来越复杂的功能。希望您也能够发现如何使用这些技术改进您自己的基于 XForms 的应用程序。

本文示例代码或素材下载

展开更多 50%)
分享

猜你喜欢

使用 JavaScript 让 XForms 变得更健壮

Web开发
使用 JavaScript 让 XForms 变得更健壮

怎么让宝宝变得更聪明?

新生儿 育儿
怎么让宝宝变得更聪明?

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

怎么让宝宝变得更聪明

电脑网络
怎么让宝宝变得更聪明

如何让宝宝变得更聪明?

育儿知识
如何让宝宝变得更聪明?

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

怎么让宝宝变得更聪明?

育儿知识
怎么让宝宝变得更聪明?

如何让孩子变得更自信

电脑网络
如何让孩子变得更自信

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

javascript对象之window对象

javascript对象之window对象

解析ASP的Application和Session对象

解析ASP的Application和Session对象
下拉加载更多内容 ↓