5.按钮控件

1.按钮简介
<Input type="button" ...>即为按钮控件，Freeform支持的按钮种类比较多，可以有如下几种：
1.平坦按钮，即无凸出边界的按钮，语法为<Input type="button" style="flat" ...>;
2.平坦全透明按钮，和平坦按钮类似，但鼠标滑过时是透明的，语法为<Input type="button" style="flat,transparent" ...>;
3.带图标的按钮，按钮中可以有一个小图标，语法为<Input type="button" icon="../res/btn.zip#33.bmp" ...>，只要该icon指向有效的url, 就是带图标按钮;
4.下拉菜单按钮，和<Menus>下某Menu关联， 其外观如下图，语法为<Input type="button" menuID="menu1" ...>;
下拉菜单按钮可以是平坦按钮，也可以是非平坦按钮，只要定义了menuID，就是下拉菜单按钮。
5.动态下拉菜单按钮，和下拉菜单按钮类似，但是其弹出的菜单是需要js动态生成或修改的，语法为<Input type="button" menuID="menu1" isDynamicMenu="true" ...>;
6.普通按钮，无平坦效果、无背景色定义、无图标、无下拉菜单的按钮就是普通按钮，普通按钮的外观由操作系统决定;
按钮按下时会触发ButtonClicked事件，对于下拉菜单按钮，当鼠标选中弹出菜单的某个菜单项，则触发MenuClicked事件。
2.动态下拉菜单按钮
下拉菜单按钮的弹出菜单是和XML描述文件中内置的<Menus>资源相关联的，但是在很多情况下，弹出什么样的下拉菜单并非事先能预知，而是需要在菜单弹出前的瞬间，收集某些状态，然后再来动态修改、或生成具体的下拉菜单。在这种情况下，必须采用动态下拉菜单按钮。
属性 isDynamicMenu 为 true 就表示是动态下拉菜单按钮， 动态下拉菜单按钮的原理分析如下：
1.当用户点击该按钮时，并不弹出菜单，而是触发MenuBeforePopup页面事件；
2.页面js须考虑修改或生成菜单，可以调用如下函数：
SetMenu() - 动态生成菜单
SetMenuItemProp() - 修改菜单项
DeleteMenuItem() - 删除菜单项
3.js最后必须调用PopupMenu( )函数，表示菜单可以弹出：
在Demo页中有具体的实例可供参考.
6.RadioButton控件

RadioButton即单选框按钮，单选框按钮必须是分组的，在每一组单选框中，各个按钮之间相互排斥，例如下面就有2组独立的单选框：
XML描述文件中假设为如下：

    //第一组
    <input GroupID="by" id="by1" selectValue="air" type="radiobutton" text="空运" value="1"/>
    <input GroupID="by" id="by2" selectValue="sea" type="radiobutton" text="水运" />
    //第二组
    <input GroupID="db" id="db1" selectValue="lon" type="radiobutton" text="银行贷款" />
    <input GroupID="db" id="db2" selectValue="pay" type="radiobutton" text="货款付乞" />

可见这2组单选框的GroupID分别为"by"、"db". 此外，每个RadioButton通常还需要定义"SelectValue"属性，表示真实的值，这样调用 GetChangedXML( ) 函数取得XML串时，结果为:

    <form level="0">
     <row>
      <by>air</by>   //"by" 是第一组的GroupID
      <db>lon</db>   //"db" 是第二组的GroupID
      ...
     </row>
    </form>

如果调用Load( )加载XML数据，同样也应该采用类似格式。
7.文件上传控件

<Input type="upload" ...>即为文件上传控件，该控件能让用户选择本地文件并上传到服务器。
文件上传有Ftp、Http二种可选途经，以下将简述二者实现原理：
1.通过Ftp上传
通过Ftp上传是最简单的实现方式，程序员不必开发服务端程序，只要部署Ftp服务器就行。在客户端的页面中，只要调用方法FtpUpload( )就能轻松完成。
2.通过Http上传
通过Http上传有三种方法：
2.1.通过Http Put直接上传
和Ftp类似，程序员也不必开发服务端程序，只要开放目标目录的写入权限即可，通过函数httpUpload()上传。
备注: 应该指定有写入权限的帐号和密码，因为权限完全开放的虚拟目录是十分不安全的。
2.2.通过Http Post发送请求
Upload控件将本地文件通过POST方式Request给服务器，服务器端需要程序员开发服务响应程序。
备注: Http Header中的Content-Type是application/octet-stream，Http Body是文件的二进制内容。
2.3.间接上传
所谓间接上传，即Upload控件只是取得文件的Base64大串，并返回给页面，由页面来处理如何发送。如果文件比较小，可以简单地以GET方式发送Base64串。
8.内嵌Freeform树

<FreeformTree　dataURL="?">是内嵌的Freeform树，组件是根据加载dataURL的数据创建树的，数据格式为XML/JSON，规范如下：
1.数据本身为普通的平面、多记录结果集;
2.每条记录须有唯一的id号;
3.每条记录允许有pid(或parantID)，指向父节点的id，以确定父子从属关系;
4.如果pid为空、或pid所指的记录不存在，则作为顶级节点;
5.每条记录必须有"freeform"属性，指向一个URL，表示以该Freeform 的XML文档创建嵌入的Freeform，该URL如果是相对URL，则是相对于本数据的URL的;
6.记录中必须以和嵌入的Feeform的Object的id同名的属性，为嵌入的Freeform对象赋值;
数据举例如下：

    <root>
    <!-- landname、countryname、imgname是嵌入的freeform中的对象id，为其赋值 -->
    <record pid="" id="01" freeform="treeland.xml" landname="欧洲"/>
    <record pid="01" id="0101" freeform="reecountry.xml" countryname="英国" imgname="uk"/>
    </root>

上例中, id、pid(或parentID)、freeform这3个属性是必需的，是系统保留词；其余的是数据，用于嵌入的freeform.
此外，FreeformTree对象支持鼠标单击、双击事件.
嵌入的Freeform不支持Menus、Upload、Pager、ImageFlow类型的Object;
嵌入的Freeform不支持输入功能.;
9.事件

Supcan FreeForm的OnEvent( id, Event, p1, p2, p3, p4 )事件含义及参数分别如下：
事件的js用法可参见“事件、按钮、菜单、工具条”Demo页。
备注1：EditKeydown和EditChar均为在输入框中的键盘事件，EditKeydown能捕获几乎所有键盘动作，包括非字符的回车、Tab等；而EditChar则以输入的字符为主，包括中文.
您可以用全局函数 CancelEvent( ) 去阻止继续执行，就如事件没有发生过那样，但不同的ASCII码，您需要在这二个事件中挑选一个执行CancelEvent( )，具体请在树列表的演示页“12.事件”中去测试;
备注2：1-Ctrl键也按下了； 2-Shift键也按下了； 3-二者一起按下了.
备注3：如果是分块上传，是类似这样的串："FileParts=33;CurrentFilePart=2;PassTime=00:02:33;RemainTime=00:01:30;Speed=50"，其含义如下：
FileParts - 总块数;
CurrentFilePart - 刚上传的块序号;
PassTime - 已耗用的时间(时:分:秒);
RemainTime - 估计还需要时间(时:分:秒);
Speed - 测算到的网速，单位为 千字节/秒;
此外，如果是将一个目录压缩成zip包上传，那么第一个Upload消息肯定是“Compressed=true”.
备注4：类似这样的串："FileSize=1002034;CurrentSize=200030;PassTime=00:02:33;RemainTime=00:01:30;Speed=50"，其含义如下：
FileSize - 文件总长度(字节);
CurrentSize - 已下载的长度(字节);
PassTime - 已耗用的时间(时:分:秒);
RemainTime - 估计还需要时间(时:分:秒);
Speed - 测算到的网速，单位为 千字节/秒;
10.XML提交格式规范

和Treelist类似，通过调用函数GetChangedXML( )，能取得输入内容的XML包，使得应用服务器能作相应处理，函数中参数level为提交级别，分如下3种：
级别0：生成当前全部、最新内容(不包括修改前的原始内容);
级别1：仅生成被修改过的Input的内容(包括原始内容);
级别2：生成全部Input的内容(包括原始内容);
级别0最常用，并且XML规范最简单，如下所示：

    <?xml version="1.0" encoding="UTF-8"?">
    <!-- id在XML描述文件中定义 -->
    <form level="0" id="?" key="?" 自定义属性="?" >
     <row>
      <!-- id处为input真实的id，Text为输入的内容 -->
      <id>Text</id>
      ...
     </row>
    </form>

级别1、2的内容规定如下：

    <?xml version="1.0" encoding="UTF-8"?">
    <!-- id 在XML描述文件中定义 -->
    <form level="?" id="?" key="?" 自定义属性="?" >
     <!-- 通过Load( )加载的是<modifiedRow>、否则就是<newRow> -->
     <modifiedRow、newRow>
      <row key="?">
       <!-- id处为input的id, origin为原始值(被修改前)，isModified仅用于级别2, Text为修改后的值 -->
       <id origin="?" isModified="false">Text</id>
       ...
      </row>
     </modifiedRow、newRow>
    </form>

警告：应用服务器端开发的程序不应过于依赖级别1/2中的origin的内容(被修改前)，因为需要考虑并发.