番外篇:jQuery表单库jquery.form.js

本主题是《云客drupal源码分析》的番外篇,在drupal系统中用于支持AJAX API,由于这是一个独立实用的库,因此专门用一个主题介绍

 

简介:

jQuery表单库(jquery.form.js库)以jQuery为基础,用于处理表单AJAX提交,使得表单AJAX提交简单、容易,且能完整控制提交过程和处理结果,不需要任何特殊标签辅助,不影响原表单结构,只要使用该库就能使普通表单平滑升级为ajax提交表单

官方地址:https://github.com/jquery-form/form

源代码查看和下载地址:https://github.com/jquery-form/form/blob/master/src/jquery.form.js

当前(201907)版本4.22

该版本对jquery的兼容性:

需要jQuery 1.7.2或更高,完全兼容jQuery 2,部分兼容jQuery 3,本篇测试环境为jquery 3.2.1,测试无问题,不兼容jQuery 3 Slim

drupal8.7版本该库版本4.22jquery 3.2.1

 

使用示例

先看一个使用示例整体感受下其魅力:


<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>jquery表单示例</title>
    <script src="jquery.min.js"></script>
    <script src="jquery.form.js"></script>
</head>
<body>
<button id="toSubmit">立即提交表单,结果显示在页头</button>
<div id="yk1"></div>
<form name="f" id="f" action="index.php" target="_blank">
    云客:<input type="text" name="yunke"><br>
    标题:<input type="text" name="title">
    <input type="submit" name="sub" value="提交">
</form>
<div id="yk2"></div>

<script type="text/javascript">
    $(function () {
        $("#f").ajaxForm({
            target: '#yk2', //正常的表单提交结果显示在页尾
        });
    });

    document.getElementById('toSubmit').onclick = function () {
        $("#f").ajaxSubmit({
            target: '#yk1', //通过事件触发的提交显示在页头
        });
    }
</script>
</body>
</html>

 

在服务器端index.php内容为:

<?php
header('Content-Type: text/html; charset=UTF-8');
echo '<pre>';
print_r($_REQUEST);
echo '</pre>';

 

主要方法介绍:

该库扩展了jquery(在其原型和属性上添加了方法),最常使用的两个方法是(通常二选一):

$.fn.ajaxSubmit( options, data, dataType, onSuccess )

在表单对应的jquery对象上调用该方法将立即提交表单,参数如下:

options:为选项对象,通过该对象可以完整控制提交过程和结果处理,详见下文

data:为额外传递到服务器的数据,数据对象方式,非字符串方式,详见选项

dataType:为ajax请求期待的数据类型,详见选项

onSuccess:为请求成功时执行的回调

该方法也可仅接收一个回调参数,将被当做请求成功时执行的回调

 

$.fn.ajaxForm( options, data, dataType, onSuccess )

该方法和ajaxSubmit方法类似,参数及含义完全相同,但她不提交表单,而是为表单绑定提交事件,并设置各种AJAX参数,相当于在为表单ajax提交做准备,当表单自然提交时(派发submit事件时,通常是点击提交按钮)将采用AJAX提交,由于该方法准备的AJAX由表单自然提交触发,因此和ajaxSubmit方法相比有以下优势:

1、如果提交是由图片表单元素触发,将包含点击坐标

2、将包含提交元素(通常是提交按钮)的name/value数据

在内部,该方法绑定的ajax提交最终还是由ajaxSubmit方法执行

 

选项参数:

在以上两个方法的选项参数中,全部标准的jquery原生$.ajax选项可用,请查阅:

   https://api.jquery.com/jQuery.ajax/

额外的或需要注意的选项如下:

beforeSerialize

表单序列化之前执行的回调函数,在取回值之前提供一个机会去操纵表单,如果返回false将阻止表单提交,回调接收两个参数:jquery包装的表单对象和选项对象

beforeSubmit

表单提交前执行的回调,如果返回false将阻止表单提交,有三个参数:数组格式的表单数据、jquery包装的表单对象和选项对象

注意:在调用顺序上,还有beforeSenddataFiltererror complete等回调,由于是jquery本身支持的,这里不再列出

filtering

处理字段前调用的回调,她提供了一个机会来过滤元素,会被这样调用:els = $.map(els, filtering);,该回调有两个参数:元素和索引

clearForm

布尔值,当提交成功后,表单是否应该清理

data

随表单一起提交的额外数据,一个数据对象,如:data: { key1: 'value1', key2: 'value2' }

extraData

该参数仅供内部使用,是data序列化成字符串之前复制的一个复本,只用于老旧浏览器AJAX上传文件的情况,也就是表单包含<input type=’file’/>并在老旧浏览器中运行的情况,在老浏览器中文件AJAX上传需要通过<iframe>来模拟提交(见下),此时extraData会转变为<input type=’hidden’/>元素包含在表单中被一起提交,现代浏览器已经不需要这种模拟了,如果同时指定了data项和该项的情况下,该项无效。虽然该参数仅供内部使用,但有些情况下外部有特殊用途,比如在选项的发送前方法(beforeSend)中,可在该参数中设置一些值,如果服务器能收到这些值,就可说明浏览器是通过iframe模拟提交的,借此做浏览器回退处理

dataType

期望服务器返回的数据类型:null"xml""script""json"之一,会影响到jquery的相关方法

delegation

布尔值,绑定事件时是否采用事件委托,事件委托可以将事件绑定到以后添加到页面的元素

iframe

布尔值,默认false,指示文件上传是否总是使用iframe方式,现在先进的浏览器基本使用XHRiframe方式是一种兼容老旧浏览器的伪ajax方式,本篇下文给了一个示例

iframeTarget

字符串值(jquery选择器),当文件上传时,指定一个iframe元素作为响应目标,默认会自动创建一个临时用iframe元素,当用该项时,不会试图处理服务器返回的响应

iframeSrc

字符串值,当iframe选项被用时,指定其src属性

forceSync

布尔值,默认false当上传文件时,是否移除传递表单前的短延迟,短延迟可以让浏览器在表单提交前执行DOM更新,比如显示一个“请稍后”的提示,该配置项仅用于明确使用iframe配置项或不支持XHR2的浏览器上传文件时

method

AJAX请求使用的http方法,如:'POST', 'GET', 'PUT'

type

method选项的别名(在原生$.ajax选项中定义),当都存在时,method优先级更高

target

收到响应后更新的元素,通常是放置响应内容的元素,或被整个替换,可以是jquery选择器、jquery对象或DOM元素对象

replaceTarget

布尔值,当使用target选项时,true表示整个替换目标,false表示仅替换目标内容,默认为false

resetForm

布尔值,指示提交成功后表单是否需要重置

semantic

布尔值,指示表单提交时,值的顺序是否严格按照表单中元素的定义顺序提交,通常是按照定义顺序提交的,但如果遇到图片提交按钮(<input type=image />),会将图片按钮的值放到最后,该项就是针对这个另外而设置,仅在表单包含图片按钮时才有用,如果为true,那么会严格按照定义顺序提交,不会将图片按钮的值放到最后,如果为false,那么会放到最后;如果服务器对值的顺序没有要求,那么设置该项将没有什么意义

success

在成功进行AJAX时执行的回调(服务器返回响应后),接收4个参数:

data:响应数据,数据格式由dataType选项值和dataFilter回调共同决定

textStatusjqXHR对象、jQuery 表单对象

该项已弃用,将用原生$.ajax选项中的success代替,换句话说将来将不再传递后两个参数

uploadProgress

执行上传进度的回调函数,如果浏览器支持,那么会传递以下四个参数:

event:浏览器事件

position:当前位置,整数

total:总数,整数

percentComplete:百分比,整数0-100之间

url

AJAX请求提交到的url地址

 

实用工具方法:

该库除ajaxFormajaxSubmit外,还为jquery原型添加了以下工具方法:

$.fn.formSerialize(semantic)

将表单序列化成一个查询字符串,如name1=value1&name2=value2,参数含义同semantic选项

 

$.fn.fieldSerialize(successful)

将匹配的字段序列化成一个查询字符串,如:

var queryString = $('#myFormId .specialFields').fieldSerialize();

先选择字段集再调用,该方法当仅仅需要表单的一部分时很有用,参数successful是一个布尔值,指示是否仅包含“成功控件successful control”,默认为true,成功控件是指能进行有效提交的控件,并非有名和值就能被提交,以下元素都不是成功控件:

1、属性disabled为真的元素

2、当表单有多个提交按钮时,没被点击的提交元素,以及重置按钮

3、没选中的复选框

4、没选中的单选按钮

5、在SELECT元素中没选中的OPTION

6、表单编码类型不支持文件时,表单中的文件元素(仅被提交文件名)

7、没name属性等等

官网对成功控件的解释请见:

http://www.w3.org/TR/html4/interact/forms.html#successful-controls

 

$.fn.formToArray(semantic, elements, filtering)

将表单值转化为数组返回,返回值类似:

[ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]

参数解释:semantic filtering含义同配置项,elements应被传递一个数组,用于收集被收集值的表单元素,这些元素会被压入数组

 

$.fieldValue(el, successful)

返回一个元素的值,该方法不是定义在jquery原型上,而是作为其属性,参数含义同上

 

$.fn.fieldValue(successful)

返回一个数组,包含匹配的表单元素的值,参数含义同上

 

$.fn.resetForm()

重置表单到原始状态

 

$.fn.clearForm(includeHidden)

清除表单值,该方法清空textpassword等能输入值的 input元素和textarea元素,重置selectradio checkbox元素到未选择状态;默认不清理按钮、hidden字段的值,但可以通过参数includeHidden来改变此行为,如果参数includeHiddentrue,那么将清除hidden元素的值,如果为jquery选择器字符串,那么将清除对应元素的值,如:$('#myForm').clearForm('.special:hidden')

 

$.fn.clearFields(includeHidden)

清除匹配表单元素的值,但仅清除表单的一部分时很有用,参数同clearForm方法

 

$.fn.enable(bool)

依据参数启用或禁用元素,参数为布尔值,true为启用,默认为true

 

$.fn.selected(select)

参数为布尔值,默认为true,针对checkboxradio元素进行是否选中设置;也可以针对select元素中的option元素,如果select元素是单选的,那么其他option元素会被取消选择,再设置本option元素是否选中,如果是多选将不会去操作其他option元素

 

$.fn.attr2(attrName)

获取元素属性的值,根据jquery的版本,当没有$.fn.prop时采用$.fn.attr方法,否则使用$.fn.prop方法,但如果属性值不是字符串也不是jquery对象,那么将再次回退使用$.fn.attr方法

 

文件iframe方式ajax上传示例:

为让读者明白什么是文件iframe方式提交,这里提供一个示例,关键点在于提交表单的target属性指向一个隐藏的iframe元素,这样提交不会导致页面整个刷新,又可以从iframe元素中取回结果

前端页面如下(自行准备jquery):


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>iframe方式文件伪ajax上传</title>
    <script src="jquery.min.js"></script>
</head>
<body>
选择文件立即上传:<input type="file" name="file"/><br>
上传结果:<div id="result"></div>

<script type="text/javascript">
    $(function () {
        // 监听文件表单change事件,有改变立即上传
        $('input[name=file]').on('change', function (e) {
            var $target = $(e.target);

            // 创建辅助用临时iframe元素
            var $frame = $('<iframe>', {name: 'upload_iframe', style: 'display: none;'});
            $frame.appendTo("body");

            //创建临时表单form 
            var $form = $('<form>', {
                method: 'POST',                 // post方式提交
                action: 'iframeUpload.php',        // 文件上传的服务器地址
                target: 'upload_iframe',         // 将结果显示到iframe元素
                enctype: 'multipart/form-data'   // 二进制数据编码
            });

            //临时将文件表单包装到表单中
            $target.wrap($form)
            //提交表单
            $target.parent().submit();

            //获取结果 处理回调
            $frame.on('load', function () {
                //去除临时用包装的form
                $target.parent().replaceWith($target);
                var result = $frame.contents().find("body").html();
                $('#result').html(result);
                //移除临时iframe元素
                $frame.remove();
            });
        });
    });

</script>
</body>
</html>

 

服务器端iframeUpload.php代码如下:

<?php
echo '<pre>';
print_r($_FILES);
echo '</pre>';

 

本书共123小节:

评论 (写第一个评论)