使用 JavaScript 让 XForms 变得更健壮

2016-02-19 17:11 1 1 收藏

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

【 tulaoshi.com - Web开发 】

  先决条件

  本文只基于 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 所示。

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

  清单 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 同步。完全不影响视图。

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

  既然模型和数据已经同步了,您可以重新绘制视图。为此,您对模型调用 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 命令。这是最后一个需要修改的地方。现在我们来运行一下修改后的示例。

  运行修改后的示例

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

  图 4. 删除最后一行

  

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

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

  

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

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

本文示例代码或素材下载

来源:https://www.tulaoshi.com/n/20160219/1614477.html

延伸阅读
如何选择易受孕期时机? 受孕是一个复杂的生理过程,必须具备下列条件:卵巢排出正常的卵子,精液中含有正常活动的精子,卵子和精子能够在输卵管内相遇并结合成为受精卵,受精卵能被送到子宫腔中,子宫内膜发肓必须适合孕卵着床,这些条件只要有一个不正常,便能阻碍 怀孕 。 女性的排卵日期一般在下次月...
标签: 亲子早教
让宝宝变得更聪明是每个家长的愿望,那么 如何让宝宝变得更聪 明呢?宝宝聪明与否除了与先天因素有关,还与周边的刺激有关,因此家长要学会对宝宝正确的教养。 如何让宝宝变得更聪明?一、要培养幼儿和父母交谈的习惯,在谈话过程中提高儿童语言的表达能力。 没有一种知识技能的传播和品德的培养,是可以离开语言来进行的。学龄前幼儿是从与...
标签: 宝宝
怎样让宝宝变得更聪明 新生的宝宝就像一张白纸,所以说宝宝的未来有一大半是作为父母能够给予的。那么我们如何让在这张洁白的纸上画上上出色的一笔呢?如何为宝宝打造一个聪明的大脑呢? 大脑发育分为两个阶段 第一个阶段,从怀孕到婴儿出生。 这个阶段我们称为大脑长数量的阶段。当婴儿出生时,大脑已经有大约100-...
标签: 宝宝
小游戏如何让孩子变得更聪明 如何让孩子更聪明 是家长们比较关心的一个育儿话题。在这个知识就是力量的时代,如何让孩子更聪明已经成为了成长教育的重点问题。所以很多家长会过早的教授孩子很多知识,其实完全不必这样,要让孩子聪明,小游戏是你的好帮手。 做被动操 抓住宝宝的胳膊,做一些伸展运动;抓住宝宝的双腿,往上抬一抬,往...
标签: 职场
同样是工作5年,有人年年加薪,顺利地从员工做到总监,还有人工资和职位都在原地踏步。从管理者的角度来看,做到下面5点,才是值得重用的好员工。 怎样让升职加薪变得更简单 1.职业目标清晰。 不少职场人工作不开心、动力不足、盲目跳槽的根本原因是职业目标不清晰。而职场生涯前3年是锻炼能力、积累资本的黄金期。如果...

经验教程

19

收藏

45
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部